mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-14 21:47:13 +00:00
Compare commits
5 Commits
jira-marku
...
0.26.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0ee97a803 | ||
|
|
63ce549ea2 | ||
|
|
0faf0ef430 | ||
|
|
cdd4b40469 | ||
|
|
54d85ebac6 |
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## 0.26.0 (27 Aug 2021)
|
||||
- Fix rendering diff between line endings ([PR #560](https://github.com/lunet-io/markdig/pull/560))
|
||||
- Make Mathematics extension respect EnableHtml* options ([PR #570](https://github.com/lunet-io/markdig/pull/570))
|
||||
|
||||
## 0.25.0 (10 June 2021)
|
||||
- Fix regression when parsing link reference definitions (#543)
|
||||
- Make digits in JiraKey's posible ([PR #548](https://github.com/lunet-io/markdig/pull/548))
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
// 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
|
||||
{
|
||||
@@ -19,25 +14,6 @@ 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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,9 +115,9 @@ namespace Markdig.Tests.RoundtripSpecs
|
||||
}
|
||||
|
||||
|
||||
//[TestCase("\n")]
|
||||
//[TestCase("\r\n")]
|
||||
//[TestCase("\r")]
|
||||
[TestCase("\n")]
|
||||
[TestCase("\r\n")]
|
||||
[TestCase("\r")]
|
||||
|
||||
[TestCase("p\n")]
|
||||
[TestCase("p\r")]
|
||||
|
||||
17
src/Markdig.Tests/TestNewLine.cs
Normal file
17
src/Markdig.Tests/TestNewLine.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Markdig.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TestNewLine
|
||||
{
|
||||
[TestCase("a \nb", "<p>a<br />\nb</p>\n")]
|
||||
[TestCase("a\\\nb", "<p>a<br />\nb</p>\n")]
|
||||
[TestCase("a `b\nc`", "<p>a <code>b c</code></p>\n")]
|
||||
public void Test(string value, string expectedHtml)
|
||||
{
|
||||
Assert.AreEqual(expectedHtml, Markdown.ToHtml(value));
|
||||
Assert.AreEqual(expectedHtml, Markdown.ToHtml(value.Replace("\n", "\r\n")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,377 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,6 @@ 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>
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
using Markdig.Parsers.Inlines;
|
||||
using Markdig.Renderers;
|
||||
using Markdig.Renderers.Normalize;
|
||||
using Markdig.Renderers.Roundtrip;
|
||||
|
||||
namespace Markdig.Extensions.CustomContainers
|
||||
{
|
||||
@@ -54,14 +52,7 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Renderers;
|
||||
@@ -16,11 +16,19 @@ namespace Markdig.Extensions.Mathematics
|
||||
protected override void Write(HtmlRenderer renderer, MathBlock obj)
|
||||
{
|
||||
renderer.EnsureLine();
|
||||
renderer.Write("<div").WriteAttributes(obj).WriteLine(">");
|
||||
renderer.WriteLine("\\[");
|
||||
renderer.WriteLeafRawLines(obj, true, true);
|
||||
renderer.Write("\\]");
|
||||
renderer.WriteLine("</div>");
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("<div").WriteAttributes(obj).WriteLine(">");
|
||||
renderer.WriteLine("\\[");
|
||||
}
|
||||
|
||||
renderer.WriteLeafRawLines(obj, true, renderer.EnableHtmlEscape);
|
||||
|
||||
if (renderer.EnableHtmlForBlock)
|
||||
{
|
||||
renderer.Write("\\]");
|
||||
renderer.WriteLine("</div>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Renderers;
|
||||
@@ -15,9 +15,24 @@ namespace Markdig.Extensions.Mathematics
|
||||
{
|
||||
protected override void Write(HtmlRenderer renderer, MathInline obj)
|
||||
{
|
||||
renderer.Write("<span").WriteAttributes(obj).Write(">\\(");
|
||||
renderer.WriteEscape(ref obj.Content);
|
||||
renderer.Write("\\)</span>");
|
||||
if (renderer.EnableHtmlForInline)
|
||||
{
|
||||
renderer.Write("<span").WriteAttributes(obj).Write(">\\(");
|
||||
}
|
||||
|
||||
if (renderer.EnableHtmlEscape)
|
||||
{
|
||||
renderer.WriteEscape(ref obj.Content);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write(ref obj.Content);
|
||||
}
|
||||
|
||||
if (renderer.EnableHtmlForInline)
|
||||
{
|
||||
renderer.Write("\\)</span>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,22 +360,6 @@ 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 < 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
@@ -4,7 +4,7 @@
|
||||
<Description>A fast, powerful, CommonMark compliant, extensible Markdown processor for .NET with 20+ builtin extensions (pipetables, footnotes, definition lists... etc.)</Description>
|
||||
<Copyright>Alexandre Mutel</Copyright>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<VersionPrefix>0.25.0</VersionPrefix>
|
||||
<VersionPrefix>0.26.0</VersionPrefix>
|
||||
<Authors>Alexandre Mutel</Authors>
|
||||
<!-- Markdig.Wpf still supports net452, a target still supported by by Microsoft until January 10, 2023 -->
|
||||
<!-- see: https://github.com/xoofx/markdig/pull/466 -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Helpers;
|
||||
@@ -63,6 +63,12 @@ namespace Markdig.Parsers.Inlines
|
||||
{
|
||||
c = ' ';
|
||||
}
|
||||
else if (c == '\r')
|
||||
{
|
||||
slice.SkipChar();
|
||||
c = slice.CurrentChar;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == match)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Alexandre Mutel. All rights reserved.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// This file is licensed under the BSD-Clause 2 license.
|
||||
// See the license.txt file in the project root for more information.
|
||||
|
||||
using Markdig.Helpers;
|
||||
@@ -66,7 +66,7 @@ namespace Markdig.Parsers.Inlines
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '\n')
|
||||
if (c == '\n' || c == '\r')
|
||||
{
|
||||
processor.Inline = new LineBreakInline()
|
||||
{
|
||||
|
||||
@@ -52,7 +52,8 @@ namespace Markdig.Parsers.Inlines
|
||||
length = nextStart - slice.Start;
|
||||
if (!processor.TrackTrivia)
|
||||
{
|
||||
if (text[nextStart] == '\n')
|
||||
var nextText = text[nextStart];
|
||||
if (nextText == '\n' || nextText == '\r')
|
||||
{
|
||||
int end = nextStart - 1;
|
||||
while (length > 0 && text[end].IsSpace())
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// 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;
|
||||
|
||||
@@ -18,53 +17,42 @@ namespace Markdig.Renderers.Roundtrip
|
||||
renderer.RenderLinesBefore(quoteBlock);
|
||||
renderer.Write(quoteBlock.TriviaBefore);
|
||||
|
||||
var quoteLines = quoteBlock.QuoteLines;
|
||||
|
||||
bool noChildren = quoteBlock.Count == 0;
|
||||
|
||||
if (quoteLines.Count > 0)
|
||||
var indents = new string[quoteBlock.QuoteLines.Count];
|
||||
for (int i = 0; i < quoteBlock.QuoteLines.Count; i++)
|
||||
{
|
||||
var indents = new string[quoteLines.Count];
|
||||
for (int i = 0; i < quoteLines.Count; i++)
|
||||
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 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)
|
||||
var emptyLeafBlock = new ParagraphBlock
|
||||
{
|
||||
renderer.WriteLine(quoteLine.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.WriteChildren(quoteBlock);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.PushIndent($"{quoteBlock.QuoteChar} ");
|
||||
|
||||
if (noChildren)
|
||||
{
|
||||
renderer.WriteLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.WriteChildren(quoteBlock);
|
||||
NewLine = quoteLine.NewLine
|
||||
};
|
||||
var newLine = new LineBreakInline
|
||||
{
|
||||
NewLine = quoteLine.NewLine
|
||||
};
|
||||
var container = new ContainerInline();
|
||||
container.AppendChild(newLine);
|
||||
emptyLeafBlock.Inline = container;
|
||||
quoteBlock.Add(emptyLeafBlock);
|
||||
}
|
||||
}
|
||||
|
||||
renderer.PushIndent(indents);
|
||||
renderer.WriteChildren(quoteBlock);
|
||||
renderer.PopIndent();
|
||||
|
||||
if (!noChildren)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,6 @@ 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>
|
||||
|
||||
@@ -14,14 +14,6 @@ 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>
|
||||
@@ -58,7 +50,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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
|
||||
/// <see cref="StringSlice.IsEmpty"/>.
|
||||
/// </summary>
|
||||
public StringSlice TriviaAfterAtxHeaderChar { get; set; }
|
||||
|
||||
@@ -61,13 +61,13 @@ namespace Markdig.Syntax
|
||||
/// <summary>
|
||||
/// Trivia occurring before this block
|
||||
/// </summary>
|
||||
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise <see cref="StringSlice.IsEmpty"/>.
|
||||
StringSlice TriviaAfter { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace Markdig.Syntax
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the trivia after the <see cref="FencedChar"/>.
|
||||
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.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="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
|
||||
/// <see cref="StringSlice.IsEmpty"/>.
|
||||
/// </summary>
|
||||
NewLine NewLine { get; set; }
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Markdig.Syntax.Inlines
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Label"/> with trivia.
|
||||
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
|
||||
/// <see cref="StringSlice.IsEmpty"/>.
|
||||
/// </summary>
|
||||
public StringSlice LabelWithTrivia { get; set; }
|
||||
|
||||
@@ -12,13 +12,6 @@ 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>
|
||||
|
||||
@@ -13,13 +13,6 @@ 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>
|
||||
@@ -37,7 +30,7 @@ namespace Markdig.Syntax
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bullet as parsed in the source document.
|
||||
/// Trivia: only parsed when <see cref="MarkdownPipeline.TrackTrivia"/> is enabled, otherwise
|
||||
/// Trivia: only parsed when <see cref="MarkdownParser.TrackTrivia"/> is enabled, otherwise
|
||||
/// <see cref="StringSlice.IsEmpty"/>.
|
||||
/// </summary>
|
||||
public StringSlice SourceBullet { get; set; }
|
||||
|
||||
@@ -14,14 +14,6 @@ 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>
|
||||
|
||||
@@ -12,13 +12,6 @@ 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>
|
||||
|
||||
@@ -6,7 +6,4 @@ 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/=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>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Markdig/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
Reference in New Issue
Block a user