diff --git a/src/Markdig.Tests/TestContainerInlines.cs b/src/Markdig.Tests/TestContainerInlines.cs new file mode 100644 index 000000000..ef79e00dc --- /dev/null +++ b/src/Markdig.Tests/TestContainerInlines.cs @@ -0,0 +1,41 @@ +using System; +using Markdig.Syntax; +using Markdig.Syntax.Inlines; +using NUnit.Framework; + +namespace Markdig.Tests +{ + public class TestContainerInlines + { + private class MockLeafBlock : LeafBlock + { + public MockLeafBlock() + : base(null) + { + + } + } + + [Test] + public void CanBeAddedToLeafBlock() + { + var leafBlock1 = new MockLeafBlock(); + + var one = new ContainerInline(); + Assert.Null(one.ParentBlock); + + leafBlock1.Inline = one; + Assert.AreSame(leafBlock1, one.ParentBlock); + + var two = new ContainerInline(); + Assert.Null(two.ParentBlock); + + leafBlock1.Inline = two; + Assert.AreSame(leafBlock1, two.ParentBlock); + Assert.Null(one.ParentBlock); + + var leafBlock2 = new MockLeafBlock(); + Assert.Throws(() => leafBlock2.Inline = two); + } + } +} diff --git a/src/Markdig/Syntax/Inlines/ContainerInline.cs b/src/Markdig/Syntax/Inlines/ContainerInline.cs index 04b4b1f69..13681d51f 100644 --- a/src/Markdig/Syntax/Inlines/ContainerInline.cs +++ b/src/Markdig/Syntax/Inlines/ContainerInline.cs @@ -17,6 +17,11 @@ namespace Markdig.Syntax.Inlines /// public class ContainerInline : Inline, IEnumerable { + /// + /// Gets the parent block of this inline. + /// + public LeafBlock ParentBlock { get; internal set; } + /// /// Gets the first child. /// diff --git a/src/Markdig/Syntax/LeafBlock.cs b/src/Markdig/Syntax/LeafBlock.cs index dbc7bacf5..67040353c 100644 --- a/src/Markdig/Syntax/LeafBlock.cs +++ b/src/Markdig/Syntax/LeafBlock.cs @@ -16,6 +16,8 @@ namespace Markdig.Syntax [DebuggerDisplay("{GetType().Name} Line: {Line}, {Lines}")] public abstract class LeafBlock : Block { + private ContainerInline inline; + /// /// Initializes a new instance of the class. /// @@ -33,7 +35,30 @@ protected LeafBlock(BlockParser parser) : base(parser) /// /// Gets or sets the inline syntax tree (may be null). /// - public ContainerInline Inline { get; set; } + public ContainerInline Inline + { + get => inline; + set + { + if (value != null) + { + if (value.Parent != null) + ThrowHelper.ArgumentException("Cannot add this inline as it as already attached to another container (inline.Parent != null)"); + + if (value.ParentBlock != null) + ThrowHelper.ArgumentException("Cannot add this inline as it as already attached to another container (inline.ParentBlock != null)"); + + value.ParentBlock = this; + } + + if (inline != null) + { + inline.ParentBlock = null; + } + + inline = value; + } + } /// /// Gets or sets a value indicating whether must be processed