Compare commits

...

7 Commits

Author SHA1 Message Date
Alexandre Mutel
6d91dc917b Temp commit 2021-08-27 20:31:31 +02:00
Alexandre Mutel
a6df957e78 Fix QuoteBlockRenderer to allow to render without QuoteLines. Also stop modifying AST while rendering. 2021-06-18 06:20:01 +02:00
Alexandre Mutel
0e0ef544f5 Start to work on a Jira Wiki Markup parser 2021-06-18 06:18:47 +02:00
Alexandre Mutel
1cbdad12ca Add InlineList to Markdig.Jira 2021-06-11 07:47:20 +02:00
Alexandre Mutel
41aa16b8b8 Add Markdig.Jira project 2021-06-11 07:47:20 +02:00
Alexandre Mutel
b2dbe59d28 Add StringSlice.IndexOfAbsolute 2021-06-11 07:47:20 +02:00
Alexandre Mutel
b5fb91235d Add parameterless constructors for blocks 2021-06-11 07:47:20 +02:00
19 changed files with 2064 additions and 46 deletions

View File

@@ -3,6 +3,11 @@
// See the license.txt file in the project root for more information.
using System;
using System.Diagnostics;
using System.IO;
using Markdig.Jira;
using Markdig.Renderers.Normalize;
using Markdig.Renderers.Roundtrip;
namespace Markdig.Tests
{
@@ -14,6 +19,25 @@ namespace Markdig.Tests
// Uncomment the following line to debug a specific tests more easily
//var tests = new Specs.CommonMarkV_0_29.TestLeafBlocksSetextHeadings();
//tests.LeafBlocksSetextHeadings_Example063();
var parser = new WikiMarkupParser();
var doc = parser.Parse("This is a *text*\n{noformat}\nYo\n{noformat}\nAnother paragraph\n");
var writer = new StringWriter();
var renderer = new RoundtripRenderer(writer);
var pipeline = new MarkdownPipelineBuilder().UseEmphasisExtras().UseCustomContainers().Build();
pipeline.Setup(renderer);
renderer.Render(doc);
var result = writer.ToString();
Console.WriteLine(result);
}
}
}

View File

@@ -0,0 +1,377 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Markdig.Collections
{
/// <summary>
/// Lightweight struct list with optimized behavior over <see cref="List{T}"/>:
/// - by ref on this[int index]
/// - AddByRef(in T item)
/// - RemoveAt returning remove item T
/// - Settable Count
/// - Underlying array accessible (pinnable...etc.)
/// - Push/Pop methods
/// </summary>
/// <typeparam name="T">Type of an item</typeparam>
[DebuggerTypeProxy(typeof(DebugListView<>)), DebuggerDisplay("Count = {Count}")]
internal struct InlineList<T> : IEnumerable<T>
{
private const int DefaultCapacity = 4;
private static readonly InlineList<T> Empty = new InlineList<T>(0);
public uint Count;
public T[] Items;
#if NET452
private static readonly T[] EmptyArray = new T[0];
#else
private static readonly T[] EmptyArray = Array.Empty<T>();
#endif
public InlineList(uint capacity)
{
Count = 0;
Items = capacity == 0 ? EmptyArray : new T[capacity];
}
public uint Capacity
{
get => (uint)(Items?.Length ?? 0);
set
{
Ensure();
if (value <= Items.Length) return;
EnsureCapacity(value);
}
}
public static InlineList<T> Create()
{
return Empty;
}
public static InlineList<T> Create(uint capacity)
{
return new InlineList<T>(capacity);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Ensure()
{
if (Items == null) Items = EmptyArray;
}
public bool IsReadOnly => false;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
if (Count > 0)
{
Array.Clear(Items, 0, (int)Count);
Count = 0;
}
}
public InlineList<T> Clone()
{
var items = (T[])Items?.Clone();
return new InlineList<T>() { Count = Count, Items = items };
}
public bool Contains(T item)
{
return Count > 0 && IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
if (array == null) throw new ArgumentNullException(nameof(array));
if (Count > 0)
{
System.Array.Copy(Items, 0, array, arrayIndex, Count);
}
}
public void Reset()
{
Clear();
Count = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T child)
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
Items[Count++] = child;
}
public ref T GetOrCreate(uint index)
{
if (index >= Count)
{
var newCount = index + 1;
EnsureCapacity(newCount);
Count = newCount;
}
return ref Items[index];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddByRef(in T child)
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
Items[Count++] = child;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T AddByRefCurrent()
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
return ref Items[Count++];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Insert(int index, T item)
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
if (index < Count)
{
Array.Copy(Items, index, Items, index + 1, Count - index);
}
Items[index] = item;
Count++;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T InsertReturnRef(int index, T item)
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
if (index < Count)
{
Array.Copy(Items, index, Items, index + 1, Count - index);
}
ref var refItem = ref Items[index];
refItem = item;
Count++;
return ref refItem;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void InsertByRef(int index, in T item)
{
if (Count == Items.Length)
{
EnsureCapacity(Count + 1);
}
if (index < Count)
{
Array.Copy(Items, index, Items, index + 1, Count - index);
}
Items[index] = item;
Count++;
}
public bool Remove(T element)
{
var index = IndexOf(element);
if (index >= 0)
{
RemoveAt((uint)index);
return true;
}
return false;
}
public int IndexOf(T element)
{
return Array.IndexOf(Items, element, 0, (int)Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T RemoveAt(uint index)
{
if (index >= Count) throw new ArgumentOutOfRangeException(nameof(index));
Count--;
// previous children
var item = Items[index];
if (index < Count)
{
Array.Copy(Items, index + 1, Items, index, Count - index);
}
Items[Count] = default(T);
return item;
}
public T RemoveLast()
{
if (Count > 0)
{
ref var removed = ref Items[Count - 1];
var copy = removed;
removed = default;
Count--;
return copy;
}
return default;
}
public ref T this[uint index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if DEBUG
if (index >= Count) throw new ArgumentOutOfRangeException(nameof(index), $"Invalid index {index} must be < {Count}");
#endif
return ref Items[index];
}
}
public void Push(T element)
{
Add(element);
}
public ref T Peek()
{
return ref Items[Count - 1];
}
public T Pop()
{
return RemoveAt(Count - 1);
}
private void EnsureCapacity(uint min)
{
if (Items.Length < min)
{
uint num = (Items.Length == 0) ? DefaultCapacity : ((uint)Items.Length) << 1;
if (num < min)
{
num = min;
}
var destinationArray = new T[num]; // ArrayPool<T>.Shared.Rent(num);
if (Count > 0)
{
Array.Copy(Items, 0, destinationArray, 0, Count);
}
if (Items.Length > 0)
{
//ArrayPool<T>.Shared.Return(Items, true);
}
Items = destinationArray;
}
}
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public struct Enumerator : IEnumerator<T>
{
private readonly InlineList<T> list;
private uint index;
private T current;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Enumerator(InlineList<T> list)
{
this.list = list;
index = 0;
current = default(T);
}
public T Current => current;
object IEnumerator.Current => Current;
public void Dispose()
{
}
public bool MoveNext()
{
if (index < list.Count)
{
current = list[index];
index++;
return true;
}
return MoveNextRare();
}
private bool MoveNextRare()
{
index = list.Count + 1;
current = default(T);
return false;
}
void IEnumerator.Reset()
{
index = 0;
current = default(T);
}
}
}
internal class DebugListView<T>
{
private readonly InlineList<T> collection;
public DebugListView(InlineList<T> collection)
{
this.collection = collection;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get
{
var array = new T[this.collection.Count];
for (uint i = 0; i < array.Length; i++)
{
array[i] = collection[i];
}
return array;
}
}
}
}

View File

@@ -15,6 +15,13 @@ namespace Markdig.Extensions.CustomContainers
/// <seealso cref="IFencedBlock" />
public class CustomContainer : ContainerBlock, IFencedBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="CustomContainer"/> class.
/// </summary>
public CustomContainer() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CustomContainer"/> class.
/// </summary>

View File

@@ -4,6 +4,8 @@
using Markdig.Parsers.Inlines;
using Markdig.Renderers;
using Markdig.Renderers.Normalize;
using Markdig.Renderers.Roundtrip;
namespace Markdig.Extensions.CustomContainers
{
@@ -52,7 +54,14 @@ namespace Markdig.Extensions.CustomContainers
htmlRenderer.ObjectRenderers.Insert(0, new HtmlCustomContainerInlineRenderer());
}
}
else if (renderer is RoundtripRenderer roundtripRenderer)
{
if (!roundtripRenderer.ObjectRenderers.Contains<RoundtripCustomContainerBlockRenderer>())
{
// Must be inserted before CodeBlockRenderer
roundtripRenderer.ObjectRenderers.Insert(0, new RoundtripCustomContainerBlockRenderer());
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
// Copyright (c) Alexandre Mutel. All rights reserved.
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using System;
using Markdig.Renderers.Normalize;
using Markdig.Syntax;
namespace Markdig.Extensions.CustomContainers
{
/// <summary>
/// An Normalize renderer for a <see cref="CodeBlock"/> and <see cref="FencedCodeBlock"/>.
/// </summary>
/// <seealso cref="NormalizeObjectRenderer{TObject}" />
public class RoundtripCustomContainerBlockRenderer : NormalizeObjectRenderer<CustomContainer>
{
protected override void Write(NormalizeRenderer renderer, CustomContainer customContainer)
{
var fencedCharCount = Math.Min(customContainer.OpeningFencedCharCount, customContainer.ClosingFencedCharCount);
var opening = new string(customContainer.FencedChar, fencedCharCount);
renderer.Write(opening);
if (customContainer.Info != null)
{
renderer.Write(customContainer.Info);
}
if (!string.IsNullOrEmpty(customContainer.Arguments))
{
renderer.Write(' ').Write(customContainer.Arguments);
}
/* TODO do we need this causes a empty space and would render html attributes to markdown.
var attributes = obj.TryGetAttributes();
if (attributes != null)
{
renderer.Write(' ');
renderer.Write(attributes);
}
*/
renderer.WriteLine();
renderer.WriteChildren(customContainer);
renderer.Write(opening);
renderer.FinishBlock(renderer.Options.EmptyLineAfterCodeBlock);
}
}
}

View File

@@ -360,6 +360,22 @@ namespace Markdig.Helpers
return Text.IndexOf(c, start, length);
}
/// <summary>
/// Searches for the specified character within this slice.
/// </summary>
/// <returns>A value >= 0 if the character was found, otherwise &lt; 0</returns>
public readonly int IndexOfAbsolute(char c, int offset)
{
if (offset > End) return -1;
int length = End - offset + 1;
if (length <= 0)
return -1;
return Text.IndexOf(c, offset, length);
}
/// <summary>
/// Trims whitespaces at the beginning of this slice starting from <see cref="Start"/> position.
/// </summary>

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@
// This file is licensed under the BSD-Clause 2 license.
// See the license.txt file in the project root for more information.
using System;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
@@ -17,42 +18,53 @@ namespace Markdig.Renderers.Roundtrip
renderer.RenderLinesBefore(quoteBlock);
renderer.Write(quoteBlock.TriviaBefore);
var indents = new string[quoteBlock.QuoteLines.Count];
for (int i = 0; i < quoteBlock.QuoteLines.Count; i++)
var quoteLines = quoteBlock.QuoteLines;
bool noChildren = quoteBlock.Count == 0;
if (quoteLines.Count > 0)
{
var quoteLine = quoteBlock.QuoteLines[i];
var wsb = quoteLine.TriviaBefore.ToString();
var quoteChar = quoteLine.QuoteChar ? ">" : "";
var spaceAfterQuoteChar = quoteLine.HasSpaceAfterQuoteChar ? " " : "";
var wsa = quoteLine.TriviaAfter.ToString();
indents[i] = (wsb + quoteChar + spaceAfterQuoteChar + wsa);
}
bool noChildren = false;
if (quoteBlock.Count == 0)
{
noChildren = true;
// since this QuoteBlock instance has no children, indents will not be rendered. We
// work around this by adding empty LineBreakInlines to a ParagraphBlock.
// Wanted: a more elegant/better solution (although this is not *that* bad).
foreach (var quoteLine in quoteBlock.QuoteLines)
var indents = new string[quoteLines.Count];
for (int i = 0; i < quoteLines.Count; i++)
{
var emptyLeafBlock = new ParagraphBlock
var quoteLine = quoteLines[i];
var wsb = quoteLine.TriviaBefore.ToString();
var quoteChar = quoteLine.QuoteChar ? ">" : "";
var spaceAfterQuoteChar = quoteLine.HasSpaceAfterQuoteChar ? " " : "";
var wsa = quoteLine.TriviaAfter.ToString();
indents[i] = (wsb + quoteChar + spaceAfterQuoteChar + wsa);
}
renderer.PushIndent(indents);
if (noChildren)
{
//// since this QuoteBlock instance has no children, indents will not be rendered. We
//// work around this by rendering explicit empty lines
foreach(var quoteLine in quoteLines)
{
NewLine = quoteLine.NewLine
};
var newLine = new LineBreakInline
{
NewLine = quoteLine.NewLine
};
var container = new ContainerInline();
container.AppendChild(newLine);
emptyLeafBlock.Inline = container;
quoteBlock.Add(emptyLeafBlock);
renderer.WriteLine(quoteLine.NewLine);
}
}
else
{
renderer.WriteChildren(quoteBlock);
}
}
else
{
renderer.PushIndent($"{quoteBlock.QuoteChar} ");
if (noChildren)
{
renderer.WriteLine();
}
else
{
renderer.WriteChildren(quoteBlock);
}
}
renderer.PushIndent(indents);
renderer.WriteChildren(quoteBlock);
renderer.PopIndent();
if (!noChildren)

View File

@@ -27,7 +27,7 @@ namespace Markdig.Syntax
/// Initializes a new instance of the <see cref="CodeBlock"/> class.
/// </summary>
/// <param name="parser">The parser.</param>
public CodeBlock(BlockParser parser) : base(parser)
public CodeBlock(BlockParser? parser) : base(parser)
{
}
}

View File

@@ -15,6 +15,13 @@ namespace Markdig.Syntax
/// </remarks>
public class FencedCodeBlock : CodeBlock, IFencedBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="FencedCodeBlock"/> class.
/// </summary>
public FencedCodeBlock() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FencedCodeBlock"/> class.
/// </summary>

View File

@@ -14,6 +14,14 @@ namespace Markdig.Syntax
[DebuggerDisplay("{GetType().Name} Line: {Line}, {Lines} Level: {Level}")]
public class HeadingBlock : LeafBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="HeadingBlock"/> class.
/// </summary>
public HeadingBlock() : base(null)
{
ProcessInlines = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="HeadingBlock"/> class.
/// </summary>
@@ -50,7 +58,7 @@ namespace Markdig.Syntax
/// <summary>
/// Gets or sets the whitespace after the # character when <see cref="IsSetext"/> is false.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
public StringSlice TriviaAfterAtxHeaderChar { get; set; }

View File

@@ -61,13 +61,13 @@ namespace Markdig.Syntax
/// <summary>
/// Trivia occurring before this block
/// </summary>
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
StringSlice TriviaBefore { get; set; }
/// <summary>
/// Trivia occurring after this block
/// </summary>
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
StringSlice TriviaAfter { get; set; }
}
}

View File

@@ -24,7 +24,7 @@ namespace Markdig.Syntax
/// <summary>
/// Gets or sets the trivia after the <see cref="FencedChar"/>.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice TriviaAfterFencedChar { get; set; }
@@ -37,14 +37,14 @@ namespace Markdig.Syntax
/// <summary>
/// Non-escaped <see cref="Info"/> exactly as in source markdown.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice UnescapedInfo { get; set; }
/// <summary>
/// Gets or sets the trivia after the <see cref="Info"/>.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice TriviaAfterInfo { get; set; }
@@ -57,28 +57,28 @@ namespace Markdig.Syntax
/// <summary>
/// Non-escaped <see cref="Arguments"/> exactly as in source markdown.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice UnescapedArguments { get; set; }
/// <summary>
/// Gets or sets the trivia after the <see cref="Arguments"/>.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice TriviaAfterArguments { get; set; }
/// <summary>
/// Newline of the line with the opening fenced chars.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
NewLine InfoNewLine { get; set; }
/// <summary>
/// Trivia before the closing fenced chars
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
StringSlice TriviaBeforeClosingFence { get; set; }
@@ -91,7 +91,7 @@ namespace Markdig.Syntax
/// <summary>
/// Newline after the last line, which is always the line containing the closing fence chars.
/// "Inherited" from <see cref="Block.NewLine"/>.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
NewLine NewLine { get; set; }

View File

@@ -34,7 +34,7 @@ namespace Markdig.Syntax.Inlines
/// <summary>
/// Gets or sets the <see cref="Label"/> with trivia.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
public StringSlice LabelWithTrivia { get; set; }

View File

@@ -12,6 +12,13 @@ namespace Markdig.Syntax
/// <seealso cref="ContainerBlock" />
public class ListBlock : ContainerBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="ListBlock"/> class.
/// </summary>
public ListBlock() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ListBlock"/> class.
/// </summary>

View File

@@ -13,6 +13,13 @@ namespace Markdig.Syntax
/// <seealso cref="ContainerBlock" />
public class ListItemBlock : ContainerBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="ListItemBlock"/> class.
/// </summary>
public ListItemBlock() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ListItemBlock"/> class.
/// </summary>
@@ -30,7 +37,7 @@ namespace Markdig.Syntax
/// <summary>
/// Gets or sets the bullet as parsed in the source document.
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
/// <see cref="StringSlice.IsEmpty"/>.
/// </summary>
public StringSlice SourceBullet { get; set; }

View File

@@ -14,6 +14,14 @@ namespace Markdig.Syntax
/// <seealso cref="ContainerBlock" />
public class QuoteBlock : ContainerBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="QuoteBlock"/> class.
/// </summary>
public QuoteBlock() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="QuoteBlock"/> class.
/// </summary>

View File

@@ -12,6 +12,13 @@ namespace Markdig.Syntax
/// </summary>
public class ThematicBreakBlock : LeafBlock
{
/// <summary>
/// Initializes a new instance of the <see cref="ThematicBreakBlock"/> class.
/// </summary>
public ThematicBreakBlock() : base(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ThematicBreakBlock"/> class.
/// </summary>

View File

@@ -6,4 +6,7 @@ See the license.txt file in the project root for more information.</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/NUnitProvider/SetCurrentDirectoryTo/@EntryValue">TestFolder</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Autolink/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Inlines/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Markdig/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jira/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Markdig/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=memset/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Renderers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>