示例#1
0
        /// <summary>
        /// Iterates over the descendant elements for the specified markdown element, including <see cref="Block"/> and <see cref="Inline"/> and filters by the type <typeparamref name="T"/>.
        /// <para>The descendant elements are returned in DFS-like order.</para>
        /// </summary>
        /// <typeparam name="T">Type to use for filtering the descendants</typeparam>
        /// <param name="markdownObject">The markdown object.</param>
        /// <returns>An iteration over the descendant elements</returns>
        public static IEnumerable <T> Descendants <T>(this MarkdownObject markdownObject) where T : MarkdownObject
        {
            if (typeof(T).IsSubclassOf(typeof(Block)))
            {
                if (markdownObject is ContainerBlock containerBlock && containerBlock.Count > 0)
                {
                    return(BlockDescendantsInternal <T>(containerBlock));
                }
            }
            else // typeof(T).IsSubclassOf(typeof(Inline)))
            {
                if (markdownObject is ContainerBlock containerBlock)
                {
                    if (containerBlock.Count > 0)
                    {
                        return(InlineDescendantsInternal <T>(containerBlock));
                    }
                }
                else if (markdownObject is ContainerInline containerInline && containerInline.FirstChild != null)
                {
                    return(containerInline.FindDescendantsInternal <T>());
                }
            }

            return(ArrayHelper.Empty <T>());
        }
示例#2
0
        /// <summary>
        /// Iterates over the descendant elements for the specified markdown element, including <see cref="Block"/> and <see cref="Inline"/>.
        /// <para>The descendant elements are returned in DFS-like order.</para>
        /// </summary>
        /// <param name="markdownObject">The markdown object.</param>
        /// <returns>An iteration over the descendant elements</returns>
        public static IEnumerable <MarkdownObject> Descendants(this MarkdownObject markdownObject)
        {
            // Fast-path an object with no children to avoid allocating Stack objects
            if (!(markdownObject is ContainerBlock) && !(markdownObject is ContainerInline))
            {
                yield break;
            }

            // TODO: A single Stack<(MarkdownObject block, bool push)> when ValueTuples are available
            Stack <MarkdownObject> stack     = new Stack <MarkdownObject>();
            Stack <bool>           pushStack = new Stack <bool>();

            stack.Push(markdownObject);
            pushStack.Push(false);

            while (stack.Count > 0)
            {
                var block = stack.Pop();
                if (pushStack.Pop())
                {
                    yield return(block);
                }
                if (block is ContainerBlock containerBlock)
                {
                    int subBlockIndex = containerBlock.Count;
                    while (subBlockIndex-- > 0)
                    {
                        var subBlock = containerBlock[subBlockIndex];
                        if (subBlock is LeafBlock leafBlock)
                        {
                            if (leafBlock.Inline != null)
                            {
                                stack.Push(leafBlock.Inline);
                                pushStack.Push(false);
                            }
                        }
                        stack.Push(subBlock);
                        pushStack.Push(true);
                    }
                }
                else if (block is ContainerInline containerInline)
                {
                    var child = containerInline.LastChild;
                    while (child != null)
                    {
                        stack.Push(child);
                        pushStack.Push(true);
                        child = child.PreviousSibling;
                    }
                }
            }
        }
        /// <summary>
        /// Iterates over the descendant elements for the specified markdown element, including <see cref="Block"/> and <see cref="Inline"/>.
        /// </summary>
        /// <param name="markdownObject">The markdown object.</param>
        /// <returns>An iteration over the descendant elements</returns>
        public static IEnumerable <MarkdownObject> Descendants(this MarkdownObject markdownObject)
        {
            // TODO: implement a recursiveless method

            var block = markdownObject as ContainerBlock;

            if (block != null)
            {
                foreach (var subBlock in block)
                {
                    yield return(subBlock);

                    foreach (var sub in subBlock.Descendants())
                    {
                        yield return(sub);
                    }

                    // Visit leaf block that have inlines
                    var leafBlock = subBlock as LeafBlock;
                    if (leafBlock?.Inline != null)
                    {
                        foreach (var subInline in Descendants(leafBlock.Inline))
                        {
                            yield return(subInline);
                        }
                    }
                }
            }
            else
            {
                var inline = markdownObject as ContainerInline;
                if (inline != null)
                {
                    var child = inline.FirstChild;
                    while (child != null)
                    {
                        var next = child.NextSibling;
                        yield return(child);

                        foreach (var sub in child.Descendants())
                        {
                            yield return(sub);
                        }

                        child = next;
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Iterates over the descendant elements for the specified markdown element, including <see cref="Block"/> and <see cref="Inline"/>.
        /// <para>The descendant elements are returned in DFS-like order.</para>
        /// </summary>
        /// <param name="markdownObject">The markdown object.</param>
        /// <returns>An iteration over the descendant elements</returns>
        public static IEnumerable <MarkdownObject> Descendants(this MarkdownObject markdownObject)
        {
            Stack <MarkdownObject> stack     = new Stack <MarkdownObject>();
            Stack <bool>           pushStack = new Stack <bool>();

            stack.Push(markdownObject);
            pushStack.Push(false);

            while (stack.Count > 0)
            {
                var block = stack.Pop();
                if (pushStack.Pop())
                {
                    yield return(block);
                }
                if (block is ContainerBlock containerBlock)
                {
                    int subBlockIndex = containerBlock.Count;
                    while (subBlockIndex-- > 0)
                    {
                        var subBlock = containerBlock[subBlockIndex];
                        if (subBlock is LeafBlock leafBlock)
                        {
                            if (leafBlock.Inline != null)
                            {
                                stack.Push(leafBlock.Inline);
                                pushStack.Push(false);
                            }
                        }
                        stack.Push(subBlock);
                        pushStack.Push(true);
                    }
                }
                else if (block is ContainerInline containerInline)
                {
                    var child = containerInline.LastChild;
                    while (child != null)
                    {
                        stack.Push(child);
                        pushStack.Push(true);
                        child = child.PreviousSibling;
                    }
                }
            }
        }
示例#5
0
        /// <summary>
        /// Determines whether the given <paramref name="url"/> points to anywhere inside the given Markdig <paramref name="element"/>.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="element">The Markdig element.</param>
        /// <returns>
        /// <c>true</c> if the given <paramref name="url"/> points to anywhere inside the given Markdig <paramref name="element"/>.; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsLinkInElement(string url, Markdig.Syntax.MarkdownObject element)
        {
            if (url.StartsWith("#"))
            {
                url = url.Substring(1);
            }

            foreach (var child in MarkdownUtilities.EnumerateAllMarkdownObjectsRecursively(element))
            {
                var    attr          = (Markdig.Renderers.Html.HtmlAttributes)child.GetData(typeof(Markdig.Renderers.Html.HtmlAttributes));
                string uniqueAddress = attr?.Id; // this header has a user defined address
                if (uniqueAddress == url)
                {
                    return(true);
                }
            }
            return(false);
        }
示例#6
0
 /// <summary>
 /// Gets the childs of a markdown object. Null is returned if no childs were to be found.
 /// </summary>
 /// <param name="parent">The markdown object from which to get the childs.</param>
 /// <returns>The childs of the given markdown object, or null.</returns>
 public static IEnumerable <Markdig.Syntax.MarkdownObject> GetChilds(this Markdig.Syntax.MarkdownObject parent)
 {
     if (parent is Markdig.Syntax.LeafBlock leafBlock)
     {
         return(leafBlock.Inline);
     }
     else if (parent is Markdig.Syntax.Inlines.ContainerInline containerInline)
     {
         return(containerInline);
     }
     else if (parent is Markdig.Syntax.ContainerBlock containerBlock)
     {
         return(containerBlock);
     }
     else
     {
         return(null);
     }
 }
示例#7
0
 /// <summary>
 /// Gets the childs of a markdown object. Null is returned if no childs were to be found.
 /// </summary>
 /// <param name="parent">The markdown object from which to get the childs.</param>
 /// <returns>The childs of the given markdown object, or null.</returns>
 public static IReadOnlyList <Markdig.Syntax.MarkdownObject> GetChildList(this Markdig.Syntax.MarkdownObject parent)
 {
     if (parent is Markdig.Syntax.LeafBlock leafBlock)
     {
         return(leafBlock.Inline?.ToArray <Markdig.Syntax.MarkdownObject>());
     }
     else if (parent is Markdig.Syntax.Inlines.ContainerInline containerInline)
     {
         return(containerInline.ToArray <Markdig.Syntax.MarkdownObject>());
     }
     else if (parent is Markdig.Syntax.ContainerBlock containerBlock)
     {
         return(containerBlock);
     }
     else
     {
         return(null);
     }
 }
        /// <summary>
        /// Iterates over the descendant elements for the specified markdown element, including <see cref="Block"/> and <see cref="Inline"/> and filters by the type <typeparamref name="T"/>.
        /// <para>The descendant elements are returned in DFS-like order.</para>
        /// </summary>
        /// <typeparam name="T">Type to use for filtering the descendants</typeparam>
        /// <param name="markdownObject">The markdown object.</param>
        /// <returns>An iteration over the descendant elements</returns>
        public static IEnumerable <T> Descendants <T>(this MarkdownObject markdownObject) where T : MarkdownObject
        {
#if UAP
            foreach (MarkdownObject descendant in markdownObject.Descendants())
            {
                if (descendant is T descendantT)
                {
                    yield return(descendantT);
                }
            }
#else
            if (typeof(T).IsSubclassOf(typeof(Block)))
            {
                if (markdownObject is ContainerBlock containerBlock && containerBlock.Count > 0)
                {
                    return(BlockDescendantsInternal <T>(containerBlock));
                }
            }
            else // typeof(T).IsSubclassOf(typeof(Inline)))
            {
                if (markdownObject is ContainerBlock containerBlock)
                {
                    if (containerBlock.Count > 0)
                    {
                        return(InlineDescendantsInternal <T>(containerBlock));
                    }
                }
                else if (markdownObject is ContainerInline containerInline && containerInline.FirstChild != null)
                {
                    return(containerInline.FindDescendantsInternal <T>());
                }
            }

            return(ArrayHelper <T> .Empty);
#endif
        }
示例#9
0
        /// <summary>
        /// Enumerates all objects in a markdown parse tree recursively, starting with the given element.
        /// </summary>
        /// <param name="startElement">The start element.</param>
        /// <returns>All text element (the given text element and all its childs).</returns>
        public static IEnumerable <Markdig.Syntax.MarkdownObject> EnumerateAllMarkdownObjectsRecursively(this Markdig.Syntax.MarkdownObject startElement)
        {
            yield return(startElement);

            var childList = GetChildList(startElement);

            if (null != childList)
            {
                foreach (var child in GetChildList(startElement))
                {
                    foreach (var childAndSub in EnumerateAllMarkdownObjectsRecursively(child))
                    {
                        yield return(childAndSub);
                    }
                }
            }
        }