mirror of
https://github.com/xoofx/markdig.git
synced 2026-02-04 05:44:50 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adce9797d6 | ||
|
|
fb71dff0ec | ||
|
|
399570941a | ||
|
|
2f903697e2 | ||
|
|
eb8fe15679 | ||
|
|
8f008e45ca | ||
|
|
0014ec4138 | ||
|
|
2ca05ccad7 | ||
|
|
6a15c804bc | ||
|
|
0446959623 | ||
|
|
e6afddbaa0 | ||
|
|
a377239e91 | ||
|
|
35aa304faf | ||
|
|
e4568979ec | ||
|
|
3470ec0d54 | ||
|
|
113ef7f215 | ||
|
|
4cb4b68883 | ||
|
|
64ae344b74 | ||
|
|
b5f3c9fc67 | ||
|
|
8a88fd0557 | ||
|
|
cc7623989d | ||
|
|
b6a7acf5fc | ||
|
|
804a6f0dbc | ||
|
|
342e264988 |
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@@ -11,25 +11,24 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install .NET 6.0, 7.0, and 8.0
|
||||
uses: actions/setup-dotnet@v1
|
||||
- name: Install .NET 6.0, and 8.0
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
7.0.x
|
||||
8.0.x
|
||||
|
||||
- name: Build, Test, Pack, Publish
|
||||
shell: bash
|
||||
run: |
|
||||
dotnet tool install -g dotnet-releaser
|
||||
dotnet tool install -g dotnet-releaser --configfile .github/workflows/nuget_org_only.config
|
||||
dotnet-releaser run --nuget-token "${{secrets.NUGET_TOKEN}}" --github-token "${{secrets.GITHUB_TOKEN}}" src/dotnet-releaser.toml
|
||||
7
.github/workflows/nuget_org_only.config
vendored
Normal file
7
.github/workflows/nuget_org_only.config
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPackable>false</IsPackable>
|
||||
@@ -19,12 +19,12 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.11" />
|
||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.11" />
|
||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
|
||||
<PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />
|
||||
<PackageReference Include="CommonMark.NET" Version="0.15.1" />
|
||||
<PackageReference Include="Markdown" Version="2.2.1" />
|
||||
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="3.1.456101" />
|
||||
<PackageReference Include="Microsoft.Diagnostics.Runtime" Version="3.1.506101" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Markdig\Markdig.csproj" />
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<StartupObject>Markdig.Tests.Program</StartupObject>
|
||||
<SpecExecutable>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net6.0\SpecFileGen.dll</SpecExecutable>
|
||||
<SpecTimestamp>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net6.0\SpecFileGen.timestamp</SpecTimestamp>
|
||||
<SpecExecutable>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net8.0\SpecFileGen.dll</SpecExecutable>
|
||||
<SpecTimestamp>$(MSBuildProjectDirectory)\..\SpecFileGen\bin\$(Configuration)\net8.0\SpecFileGen.timestamp</SpecTimestamp>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -51,6 +51,16 @@ public class TestNormalize
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SyntaxHeadlineLevel7()
|
||||
{
|
||||
AssertSyntax("####### Headline", new HeadingBlock(null) {
|
||||
HeaderChar = '#',
|
||||
Level = 7,
|
||||
Inline = new ContainerInline().AppendChild(new LiteralInline("Headline")),
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SyntaxParagraph()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>Markdig.WebApp</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -20,7 +20,7 @@ public class AbbreviationParser : BlockParser
|
||||
/// </summary>
|
||||
public AbbreviationParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '*' };
|
||||
OpeningCharacters = ['*'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -2,8 +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.IO;
|
||||
|
||||
using Markdig.Helpers;
|
||||
using Markdig.Parsers;
|
||||
using Markdig.Renderers;
|
||||
|
||||
@@ -11,14 +11,9 @@ namespace Markdig.Extensions.AutoLinks;
|
||||
/// Extension to automatically create <see cref="LinkInline"/> when a link url http: or mailto: is found.
|
||||
/// </summary>
|
||||
/// <seealso cref="IMarkdownExtension" />
|
||||
public class AutoLinkExtension : IMarkdownExtension
|
||||
public class AutoLinkExtension(AutoLinkOptions? options) : IMarkdownExtension
|
||||
{
|
||||
public readonly AutoLinkOptions Options;
|
||||
|
||||
public AutoLinkExtension(AutoLinkOptions? options)
|
||||
{
|
||||
Options = options ?? new AutoLinkOptions();
|
||||
}
|
||||
public readonly AutoLinkOptions Options = options ?? new AutoLinkOptions();
|
||||
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
{
|
||||
|
||||
@@ -22,14 +22,14 @@ public class AutoLinkParser : InlineParser
|
||||
{
|
||||
Options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
|
||||
OpeningCharacters = new char[]
|
||||
{
|
||||
OpeningCharacters =
|
||||
[
|
||||
'h', // for http:// and https://
|
||||
'f', // for ftp://
|
||||
'm', // for mailto:
|
||||
't', // for tel:
|
||||
'w', // for www.
|
||||
};
|
||||
];
|
||||
|
||||
_listOfCharCache = new ListOfCharCache();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class CustomContainerParser : FencedBlockParserBase<CustomContainer>
|
||||
/// </summary>
|
||||
public CustomContainerParser()
|
||||
{
|
||||
OpeningCharacters = new [] {':'};
|
||||
OpeningCharacters = [':'];
|
||||
|
||||
// We don't need a prefix
|
||||
InfoPrefix = null;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class DefinitionListParser : BlockParser
|
||||
/// </summary>
|
||||
public DefinitionListParser()
|
||||
{
|
||||
OpeningCharacters = new [] {':', '~'};
|
||||
OpeningCharacters = [':', '~'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -1786,6 +1786,6 @@ public class EmojiMapping
|
||||
ThrowHelper.ArgumentException(string.Format("Smiley {0} is already present in the emoji mapping", smiley.Key));
|
||||
}
|
||||
|
||||
OpeningCharacters = new List<char>(firstChars).ToArray();
|
||||
OpeningCharacters = [.. firstChars];
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public class FigureBlockParser : BlockParser
|
||||
/// </summary>
|
||||
public FigureBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '^' };
|
||||
OpeningCharacters = ['^'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -19,7 +19,7 @@ public class FooterBlockParser : BlockParser
|
||||
/// </summary>
|
||||
public FooterBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'^'};
|
||||
OpeningCharacters = ['^'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -22,7 +22,7 @@ public class FootnoteParser : BlockParser
|
||||
|
||||
public FootnoteParser()
|
||||
{
|
||||
OpeningCharacters = new [] {'['};
|
||||
OpeningCharacters = ['['];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
@@ -49,7 +49,7 @@ public class FootnoteParser : BlockParser
|
||||
|
||||
// Advance the column
|
||||
int deltaColumn = processor.Start - start;
|
||||
processor.Column = processor.Column + deltaColumn;
|
||||
processor.Column += deltaColumn;
|
||||
|
||||
processor.NextChar(); // Skip ':'
|
||||
|
||||
@@ -170,10 +170,8 @@ public class FootnoteParser : BlockParser
|
||||
paragraphBlock = new ParagraphBlock();
|
||||
footnote.Add(paragraphBlock);
|
||||
}
|
||||
if (paragraphBlock.Inline == null)
|
||||
{
|
||||
paragraphBlock.Inline = new ContainerInline();
|
||||
}
|
||||
|
||||
paragraphBlock.Inline ??= new ContainerInline();
|
||||
|
||||
foreach (var link in footnote.Links)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ public class GenericAttributesParser : InlineParser
|
||||
/// </summary>
|
||||
public GenericAttributesParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '{' };
|
||||
OpeningCharacters = ['{'];
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
@@ -136,10 +136,7 @@ public class GenericAttributesParser : InlineParser
|
||||
var text = slice.Text.Substring(start, end - start + 1);
|
||||
if (isClass)
|
||||
{
|
||||
if (classes is null)
|
||||
{
|
||||
classes = new List<string>();
|
||||
}
|
||||
classes ??= new List<string>();
|
||||
classes.Add(text);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -20,7 +20,7 @@ public class MathBlockParser : FencedBlockParserBase<MathBlock>
|
||||
/// </summary>
|
||||
public MathBlockParser()
|
||||
{
|
||||
OpeningCharacters = new [] {'$'};
|
||||
OpeningCharacters = ['$'];
|
||||
// We expect to match only a $$, no less, no more
|
||||
MinimumMatchCount = 2;
|
||||
MaximumMatchCount = 2;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class MathInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public MathInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '$' };
|
||||
OpeningCharacters = ['$'];
|
||||
DefaultClass = "math";
|
||||
}
|
||||
|
||||
|
||||
@@ -11,23 +11,19 @@ namespace Markdig.Extensions.MediaLinks;
|
||||
|
||||
public class HostProviderBuilder
|
||||
{
|
||||
private sealed class DelegateProvider : IHostProvider
|
||||
private sealed class DelegateProvider(
|
||||
string hostPrefix,
|
||||
Func<Uri, string?> handler,
|
||||
bool allowFullscreen = true,
|
||||
string? className = null) : IHostProvider
|
||||
{
|
||||
public DelegateProvider(string hostPrefix, Func<Uri, string?> handler, bool allowFullscreen = true, string? className = null)
|
||||
{
|
||||
HostPrefix = hostPrefix;
|
||||
Delegate = handler;
|
||||
AllowFullScreen = allowFullscreen;
|
||||
Class = className;
|
||||
}
|
||||
public string HostPrefix { get; } = hostPrefix;
|
||||
|
||||
public string HostPrefix { get; }
|
||||
public Func<Uri, string?> Delegate { get; } = handler;
|
||||
|
||||
public Func<Uri, string?> Delegate { get; }
|
||||
public bool AllowFullScreen { get; } = allowFullscreen;
|
||||
|
||||
public bool AllowFullScreen { get; }
|
||||
|
||||
public string? Class { get; }
|
||||
public string? Class { get; } = className;
|
||||
|
||||
public bool TryHandle(Uri mediaUri, bool isSchemaRelative, [NotNullWhen(true)] out string? iframeUrl)
|
||||
{
|
||||
@@ -71,7 +67,7 @@ public class HostProviderBuilder
|
||||
|
||||
#region Known providers
|
||||
|
||||
private static readonly string[] SplitAnd = { "&" };
|
||||
private static readonly string[] SplitAnd = ["&"];
|
||||
private static string[] SplitQuery(Uri uri)
|
||||
{
|
||||
var query = uri.Query.Substring(uri.Query.IndexOf('?') + 1);
|
||||
|
||||
@@ -17,7 +17,7 @@ public class NoFollowLinksExtension : IMarkdownExtension
|
||||
|
||||
public NoFollowLinksExtension()
|
||||
{
|
||||
_referralLinksExtension = new ReferralLinksExtension(new[] { "nofollow" });
|
||||
_referralLinksExtension = new ReferralLinksExtension(["nofollow"]);
|
||||
}
|
||||
|
||||
public void Setup(MarkdownPipelineBuilder pipeline)
|
||||
|
||||
@@ -19,7 +19,7 @@ public class SmartyPantsInlineParser : InlineParser, IPostInlineProcessor
|
||||
/// </summary>
|
||||
public SmartyPantsInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'\'', '"', '<', '>', '.', '-'};
|
||||
OpeningCharacters = ['\'', '"', '<', '>', '.', '-'];
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
|
||||
@@ -12,7 +12,7 @@ public class GridTableParser : BlockParser
|
||||
{
|
||||
public GridTableParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '+' };
|
||||
OpeningCharacters = ['+'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
@@ -144,7 +144,7 @@ public class GridTableParser : BlockParser
|
||||
line.Start = lineStart + columnSlice.Start + 1;
|
||||
line.End = lineStart + columnSlice.End - 1;
|
||||
line.Trim();
|
||||
if (line.IsEmptyOrWhitespace() || !IsRowSeperator(line))
|
||||
if (line.IsEmptyOrWhitespace() || !IsRowSeparator(line))
|
||||
{
|
||||
hasRowSpan = true;
|
||||
columnSlice.CurrentCell.RowSpan++;
|
||||
@@ -158,7 +158,7 @@ public class GridTableParser : BlockParser
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsRowSeperator(StringSlice slice)
|
||||
private static bool IsRowSeparator(StringSlice slice)
|
||||
{
|
||||
char c = slice.CurrentChar;
|
||||
do
|
||||
@@ -263,7 +263,7 @@ public class GridTableParser : BlockParser
|
||||
}
|
||||
sliceForCell.TrimEnd();
|
||||
|
||||
if (!isRowLine || !IsRowSeperator(sliceForCell))
|
||||
if (!isRowLine || !IsRowSeparator(sliceForCell))
|
||||
{
|
||||
if (columnSlice.CurrentCell is null)
|
||||
{
|
||||
@@ -273,10 +273,7 @@ public class GridTableParser : BlockParser
|
||||
ColumnIndex = i
|
||||
};
|
||||
|
||||
if (columnSlice.BlockProcessor is null)
|
||||
{
|
||||
columnSlice.BlockProcessor = processor.CreateChild();
|
||||
}
|
||||
columnSlice.BlockProcessor ??= processor.CreateChild();
|
||||
|
||||
// Ensure that the BlockParser is aware that the TableCell is the top-level container
|
||||
columnSlice.BlockProcessor.Open(columnSlice.CurrentCell);
|
||||
|
||||
@@ -10,21 +10,15 @@ namespace Markdig.Extensions.Tables;
|
||||
/// <summary>
|
||||
/// Internal state used by the <see cref="GridTableParser"/>
|
||||
/// </summary>
|
||||
internal sealed class GridTableState
|
||||
internal sealed class GridTableState(int start, bool expectRow)
|
||||
{
|
||||
public GridTableState(int start, bool expectRow)
|
||||
{
|
||||
Start = start;
|
||||
ExpectRow = expectRow;
|
||||
}
|
||||
|
||||
public int Start { get; }
|
||||
public int Start { get; } = start;
|
||||
|
||||
public StringLineGroup Lines;
|
||||
|
||||
public List<ColumnSlice>? ColumnSlices { get; private set; }
|
||||
|
||||
public bool ExpectRow { get; }
|
||||
public bool ExpectRow { get; } = expectRow;
|
||||
|
||||
public int StartRowGroup { get; set; }
|
||||
|
||||
@@ -45,26 +39,18 @@ internal sealed class GridTableState
|
||||
ColumnSlices.Add(new ColumnSlice(start, end, align));
|
||||
}
|
||||
|
||||
public sealed class ColumnSlice
|
||||
public sealed class ColumnSlice(int start, int end, TableColumnAlign? align)
|
||||
{
|
||||
public ColumnSlice(int start, int end, TableColumnAlign? align)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
Align = align;
|
||||
CurrentColumnSpan = -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the index position of this column (after the |)
|
||||
/// </summary>
|
||||
public int Start { get; }
|
||||
public int Start { get; } = start;
|
||||
|
||||
public int End { get; }
|
||||
public int End { get; } = end;
|
||||
|
||||
public TableColumnAlign? Align { get; }
|
||||
public TableColumnAlign? Align { get; } = align;
|
||||
|
||||
public int CurrentColumnSpan { get; set; }
|
||||
public int CurrentColumnSpan { get; set; } = -1;
|
||||
|
||||
public int PreviousColumnSpan { get; set; }
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class PipeTableBlockParser : BlockParser
|
||||
/// </summary>
|
||||
public PipeTableBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'-'};
|
||||
OpeningCharacters = ['-'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -25,12 +25,12 @@ public class PipeTableParser : InlineParser, IPostInlineProcessor
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PipeTableParser" /> class.
|
||||
/// </summary>
|
||||
/// <param name="lineBreakParser">The linebreak parser to use</param>
|
||||
/// <param name="lineBreakParser">The line break parser to use</param>
|
||||
/// <param name="options">The options.</param>
|
||||
public PipeTableParser(LineBreakInlineParser lineBreakParser, PipeTableOptions? options = null)
|
||||
{
|
||||
this.lineBreakParser = lineBreakParser ?? throw new ArgumentNullException(nameof(lineBreakParser));
|
||||
OpeningCharacters = new[] { '|', '\n', '\r' };
|
||||
OpeningCharacters = ['|', '\n', '\r'];
|
||||
Options = options ?? new PipeTableOptions();
|
||||
}
|
||||
|
||||
@@ -637,10 +637,10 @@ public class PipeTableParser : InlineParser, IPostInlineProcessor
|
||||
|
||||
public int LineIndex { get; set; }
|
||||
|
||||
public List<Inline> ColumnAndLineDelimiters { get; } = new();
|
||||
public List<Inline> ColumnAndLineDelimiters { get; } = [];
|
||||
|
||||
public List<TableCell> Cells { get; } = new();
|
||||
public List<TableCell> Cells { get; } = [];
|
||||
|
||||
public List<Inline> EndOfLines { get; } = new();
|
||||
public List<Inline> EndOfLines { get; } = [];
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class TaskListInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public TaskListInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'['};
|
||||
OpeningCharacters = ['['];
|
||||
ListClass = "contains-task-list";
|
||||
ListItemClass = "task-list-item";
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class YamlFrontMatterParser : BlockParser
|
||||
/// </summary>
|
||||
public YamlFrontMatterParser()
|
||||
{
|
||||
this.OpeningCharacters = new[] { '-' };
|
||||
OpeningCharacters = ['-'];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,14 +7,9 @@ using Markdig.Syntax;
|
||||
namespace Markdig.Helpers;
|
||||
|
||||
// Used to avoid the overhead of type covariance checks
|
||||
internal readonly struct BlockWrapper : IEquatable<BlockWrapper>
|
||||
internal readonly struct BlockWrapper(Block block) : IEquatable<BlockWrapper>
|
||||
{
|
||||
public readonly Block Block;
|
||||
|
||||
public BlockWrapper(Block block)
|
||||
{
|
||||
Block = block;
|
||||
}
|
||||
public readonly Block Block = block;
|
||||
|
||||
public static implicit operator Block(BlockWrapper wrapper) => wrapper.Block;
|
||||
|
||||
|
||||
@@ -722,11 +722,11 @@ public static class CharHelper
|
||||
}
|
||||
|
||||
// Used by ListExtraItemParser to format numbers from 1 - 26
|
||||
private static readonly string[] smallNumberStringCache = {
|
||||
private static readonly string[] smallNumberStringCache = [
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
|
||||
"20", "21", "22", "23", "24", "25", "26",
|
||||
};
|
||||
];
|
||||
|
||||
internal static string SmallNumberToString(int number)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ public sealed class CharacterMap<T> where T : class
|
||||
charSet.Add(map.Key);
|
||||
}
|
||||
|
||||
OpeningCharacters = charSet.ToArray();
|
||||
OpeningCharacters = [.. charSet];
|
||||
Array.Sort(OpeningCharacters);
|
||||
|
||||
_asciiMap = new T[128];
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Markdig.Helpers;
|
||||
/// </summary>
|
||||
public static class HtmlHelper
|
||||
{
|
||||
private static readonly char[] SearchBackAndAmp = { '\\', '&' };
|
||||
private static readonly char[] SearchAmp = { '&' };
|
||||
private static readonly char[] SearchBackAndAmp = ['\\', '&'];
|
||||
private static readonly char[] SearchAmp = ['&'];
|
||||
private static readonly string[] EscapeUrlsForAscii = new string[128];
|
||||
|
||||
static HtmlHelper()
|
||||
|
||||
@@ -187,16 +187,10 @@ public struct StringLineGroup : IEnumerable
|
||||
}
|
||||
}
|
||||
|
||||
public struct Enumerator : IEnumerator
|
||||
public struct Enumerator(StringLineGroup parent) : IEnumerator
|
||||
{
|
||||
private readonly StringLineGroup _parent;
|
||||
private int _index;
|
||||
|
||||
public Enumerator(StringLineGroup parent)
|
||||
{
|
||||
_parent = parent;
|
||||
_index = -1;
|
||||
}
|
||||
private readonly StringLineGroup _parent = parent;
|
||||
private int _index = -1;
|
||||
|
||||
public object Current => _parent.Lines[_index];
|
||||
|
||||
@@ -452,25 +446,21 @@ public struct StringLineGroup : IEnumerable
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct LineOffset
|
||||
public readonly struct LineOffset(
|
||||
int linePosition,
|
||||
int column,
|
||||
int offset,
|
||||
int start,
|
||||
int end)
|
||||
{
|
||||
public LineOffset(int linePosition, int column, int offset, int start, int end)
|
||||
{
|
||||
LinePosition = linePosition;
|
||||
Column = column;
|
||||
Offset = offset;
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
public readonly int LinePosition = linePosition;
|
||||
|
||||
public readonly int LinePosition;
|
||||
public readonly int Column = column;
|
||||
|
||||
public readonly int Column;
|
||||
public readonly int Offset = offset;
|
||||
|
||||
public readonly int Offset;
|
||||
public readonly int Start = start;
|
||||
|
||||
public readonly int Start;
|
||||
|
||||
public readonly int End;
|
||||
public readonly int End = end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,18 +95,14 @@ public sealed class MarkdownPipeline
|
||||
return new RentedHtmlRenderer(cache, renderer);
|
||||
}
|
||||
|
||||
internal sealed class HtmlRendererCache : ObjectCache<HtmlRenderer>
|
||||
internal sealed class HtmlRendererCache(
|
||||
MarkdownPipeline pipeline,
|
||||
bool customWriter = false) : ObjectCache<HtmlRenderer>
|
||||
{
|
||||
private static readonly TextWriter s_dummyWriter = new FastStringWriter();
|
||||
private static readonly FastStringWriter s_dummyWriter = new();
|
||||
|
||||
private readonly MarkdownPipeline _pipeline;
|
||||
private readonly bool _customWriter;
|
||||
|
||||
public HtmlRendererCache(MarkdownPipeline pipeline, bool customWriter = false)
|
||||
{
|
||||
_pipeline = pipeline;
|
||||
_customWriter = customWriter;
|
||||
}
|
||||
private readonly MarkdownPipeline _pipeline = pipeline;
|
||||
private readonly bool _customWriter = customWriter;
|
||||
|
||||
protected override HtmlRenderer NewInstance()
|
||||
{
|
||||
|
||||
@@ -24,8 +24,8 @@ public class MarkdownPipelineBuilder
|
||||
public MarkdownPipelineBuilder()
|
||||
{
|
||||
// Add all default parsers
|
||||
BlockParsers = new OrderedList<BlockParser>()
|
||||
{
|
||||
BlockParsers =
|
||||
[
|
||||
new ThematicBreakParser(),
|
||||
new HeadingBlockParser(),
|
||||
new QuoteBlockParser(),
|
||||
@@ -35,10 +35,10 @@ public class MarkdownPipelineBuilder
|
||||
new FencedCodeBlockParser(),
|
||||
new IndentedCodeBlockParser(),
|
||||
new ParagraphBlockParser(),
|
||||
};
|
||||
];
|
||||
|
||||
InlineParsers = new OrderedList<InlineParser>()
|
||||
{
|
||||
InlineParsers =
|
||||
[
|
||||
new HtmlEntityParser(),
|
||||
new LinkInlineParser(),
|
||||
new EscapeInlineParser(),
|
||||
@@ -46,7 +46,7 @@ public class MarkdownPipelineBuilder
|
||||
new CodeInlineParser(),
|
||||
new AutolinkInlineParser(),
|
||||
new LineBreakInlineParser(),
|
||||
};
|
||||
];
|
||||
|
||||
Extensions = new OrderedList<IMarkdownExtension>();
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public class BlockProcessor
|
||||
/// <summary>
|
||||
/// Gets the current stack of <see cref="Block"/> being processed.
|
||||
/// </summary>
|
||||
private List<BlockWrapper> OpenedBlocks { get; } = new();
|
||||
private List<BlockWrapper> OpenedBlocks { get; } = [];
|
||||
|
||||
private bool ContinueProcessingLine { get; set; }
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public class FencedCodeBlockParser : FencedBlockParserBase<FencedCodeBlock>
|
||||
/// </summary>
|
||||
public FencedCodeBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'`', '~'};
|
||||
OpeningCharacters = ['`', '~'];
|
||||
InfoPrefix = DefaultInfoPrefix;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public class HeadingBlockParser : BlockParser, IAttributesParseable
|
||||
/// </summary>
|
||||
public HeadingBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'#'};
|
||||
OpeningCharacters = ['#'];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ public class HtmlBlockParser : BlockParser
|
||||
/// </summary>
|
||||
public HtmlBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '<' };
|
||||
OpeningCharacters = ['<'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -26,7 +26,7 @@ public delegate void ProcessInlineDelegate(InlineProcessor processor, Inline? in
|
||||
/// </summary>
|
||||
public class InlineProcessor
|
||||
{
|
||||
private readonly List<StringLineGroup.LineOffset> lineOffsets = new();
|
||||
private readonly List<StringLineGroup.LineOffset> lineOffsets = [];
|
||||
private int previousSliceOffset;
|
||||
private int previousLineIndexForSliceOffset;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class AutolinkInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public AutolinkInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'<'};
|
||||
OpeningCharacters = ['<'];
|
||||
EnableHtmlParsing = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class CodeInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public CodeInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '`' };
|
||||
OpeningCharacters = ['`'];
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Markdig.Parsers.Inlines;
|
||||
public class EmphasisInlineParser : InlineParser, IPostInlineProcessor
|
||||
{
|
||||
private CharacterMap<EmphasisDescriptor>? emphasisMap;
|
||||
private readonly DelimitersObjectCache inlinesCache = new DelimitersObjectCache();
|
||||
private readonly DelimitersObjectCache inlinesCache = new();
|
||||
|
||||
[Obsolete("Use TryCreateEmphasisInlineDelegate instead", error: false)]
|
||||
public delegate EmphasisInline CreateEmphasisInlineDelegate(char emphasisChar, bool isStrong);
|
||||
@@ -31,11 +31,11 @@ public class EmphasisInlineParser : InlineParser, IPostInlineProcessor
|
||||
/// </summary>
|
||||
public EmphasisInlineParser()
|
||||
{
|
||||
EmphasisDescriptors = new List<EmphasisDescriptor>()
|
||||
{
|
||||
EmphasisDescriptors =
|
||||
[
|
||||
new EmphasisDescriptor('*', 1, 2, true),
|
||||
new EmphasisDescriptor('_', 1, 2, false)
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -65,7 +65,7 @@ public class EmphasisInlineParser : InlineParser, IPostInlineProcessor
|
||||
/// </summary>
|
||||
[Obsolete("Use TryCreateEmphasisInlineList instead", error: false)]
|
||||
public CreateEmphasisInlineDelegate? CreateEmphasisInline { get; set; }
|
||||
public readonly List<TryCreateEmphasisInlineDelegate> TryCreateEmphasisInlineList = new List<TryCreateEmphasisInlineDelegate>();
|
||||
public readonly List<TryCreateEmphasisInlineDelegate> TryCreateEmphasisInlineList = [];
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ public class EscapeInlineParser : InlineParser
|
||||
{
|
||||
public EscapeInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'\\'};
|
||||
OpeningCharacters = ['\\'];
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
|
||||
@@ -21,7 +21,7 @@ public class HtmlEntityParser : InlineParser
|
||||
/// </summary>
|
||||
public HtmlEntityParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'&'};
|
||||
OpeningCharacters = ['&'];
|
||||
}
|
||||
|
||||
public static bool TryParse(ref StringSlice slice, [NotNullWhen(true)] out string? literal, out int match)
|
||||
|
||||
@@ -18,7 +18,7 @@ public class LineBreakInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public LineBreakInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] { '\n', '\r' };
|
||||
OpeningCharacters = ['\n', '\r'];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -19,7 +19,7 @@ public class LinkInlineParser : InlineParser
|
||||
/// </summary>
|
||||
public LinkInlineParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'[', ']', '!'};
|
||||
OpeningCharacters = ['[', ']', '!'];
|
||||
}
|
||||
|
||||
public override bool Match(InlineProcessor processor, ref StringSlice slice)
|
||||
@@ -322,7 +322,7 @@ public class LinkInlineParser : InlineParser
|
||||
|
||||
if (label != null || LinkHelper.TryParseLabelTrivia(ref text, true, out label, out labelSpan))
|
||||
{
|
||||
SourceSpan labelWithTrivia = new SourceSpan(labelSpan.Start, labelSpan.End);
|
||||
var labelWithTrivia = new SourceSpan(labelSpan.Start, labelSpan.End);
|
||||
if (isLabelSpanLocal)
|
||||
{
|
||||
labelSpan = inlineState.GetSourcePositionFromLocalSpan(labelSpan);
|
||||
|
||||
@@ -210,16 +210,10 @@ public static class MarkdownParser
|
||||
}
|
||||
}
|
||||
|
||||
private struct ContainerItem
|
||||
private struct ContainerItem(ContainerBlock container)
|
||||
{
|
||||
public ContainerItem(ContainerBlock container)
|
||||
{
|
||||
Container = container;
|
||||
Index = 0;
|
||||
}
|
||||
public readonly ContainerBlock Container = container;
|
||||
|
||||
public readonly ContainerBlock Container;
|
||||
|
||||
public int Index;
|
||||
public int Index = 0;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public abstract class OrderedListItemParser : ListItemParser
|
||||
/// </summary>
|
||||
protected OrderedListItemParser()
|
||||
{
|
||||
OrderedDelimiters = new[] { '.', ')' };
|
||||
OrderedDelimiters = ['.', ')'];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -18,7 +18,7 @@ public class QuoteBlockParser : BlockParser
|
||||
/// </summary>
|
||||
public QuoteBlockParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'>'};
|
||||
OpeningCharacters = ['>'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -16,14 +16,14 @@ public class ThematicBreakParser : BlockParser
|
||||
/// <summary>
|
||||
/// A singleton instance used by other parsers.
|
||||
/// </summary>
|
||||
public static readonly ThematicBreakParser Default = new ThematicBreakParser();
|
||||
public static readonly ThematicBreakParser Default = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ThematicBreakParser"/> class.
|
||||
/// </summary>
|
||||
public ThematicBreakParser()
|
||||
{
|
||||
OpeningCharacters = new[] {'-', '_', '*'};
|
||||
OpeningCharacters = ['-', '_', '*'];
|
||||
}
|
||||
|
||||
public override BlockState TryOpen(BlockProcessor processor)
|
||||
|
||||
@@ -15,7 +15,7 @@ public class UnorderedListItemParser : ListItemParser
|
||||
/// </summary>
|
||||
public UnorderedListItemParser()
|
||||
{
|
||||
OpeningCharacters = new [] {'-', '+', '*'};
|
||||
OpeningCharacters = ['-', '+', '*'];
|
||||
}
|
||||
|
||||
public override bool TryParse(BlockProcessor state, char pendingBulletType, out ListInfo result)
|
||||
|
||||
@@ -23,7 +23,7 @@ internal sealed class AllowNullAttribute : Attribute { }
|
||||
#if !NET5_0_OR_GREATER
|
||||
internal sealed class MemberNotNullAttribute : Attribute
|
||||
{
|
||||
public MemberNotNullAttribute(string member) => Members = new[] { member };
|
||||
public MemberNotNullAttribute(string member) => Members = [member];
|
||||
|
||||
public MemberNotNullAttribute(params string[] members) => Members = members;
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ namespace Markdig.Renderers.Html;
|
||||
/// <seealso cref="HtmlObjectRenderer{HeadingBlock}" />
|
||||
public class HeadingRenderer : HtmlObjectRenderer<HeadingBlock>
|
||||
{
|
||||
private static readonly string[] HeadingTexts = {
|
||||
private static readonly string[] HeadingTexts = [
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
};
|
||||
];
|
||||
|
||||
protected override void Write(HtmlRenderer renderer, HeadingBlock obj)
|
||||
{
|
||||
|
||||
@@ -144,6 +144,8 @@ public class HtmlRenderer : TextRendererBase<HtmlRenderer>
|
||||
return this;
|
||||
}
|
||||
|
||||
private static readonly SearchValues<char> s_escapedChars = SearchValues.Create("<>&\"");
|
||||
|
||||
/// <summary>
|
||||
/// Writes the content escaped for HTML.
|
||||
/// </summary>
|
||||
@@ -159,7 +161,7 @@ public class HtmlRenderer : TextRendererBase<HtmlRenderer>
|
||||
{
|
||||
int indexOfCharToEscape = softEscape
|
||||
? content.IndexOfAny('<', '&')
|
||||
: content.IndexOfAny("<>&\"");
|
||||
: content.IndexOfAny(s_escapedChars);
|
||||
|
||||
if ((uint)indexOfCharToEscape >= (uint)content.Length)
|
||||
{
|
||||
|
||||
@@ -18,9 +18,9 @@ public class CodeBlockRenderer : NormalizeObjectRenderer<CodeBlock>
|
||||
{
|
||||
if (obj is FencedCodeBlock fencedCodeBlock)
|
||||
{
|
||||
var fencedCharCount = Math.Min(fencedCodeBlock.OpeningFencedCharCount, fencedCodeBlock.ClosingFencedCharCount);
|
||||
var opening = new string(fencedCodeBlock.FencedChar, fencedCharCount);
|
||||
renderer.Write(opening);
|
||||
int fencedCharCount = Math.Min(fencedCodeBlock.OpeningFencedCharCount, fencedCodeBlock.ClosingFencedCharCount);
|
||||
|
||||
renderer.Write(fencedCodeBlock.FencedChar, fencedCharCount);
|
||||
if (fencedCodeBlock.Info != null)
|
||||
{
|
||||
renderer.Write(fencedCodeBlock.Info);
|
||||
@@ -41,7 +41,7 @@ public class CodeBlockRenderer : NormalizeObjectRenderer<CodeBlock>
|
||||
renderer.WriteLine();
|
||||
|
||||
renderer.WriteLeafRawLines(obj, true);
|
||||
renderer.Write(opening);
|
||||
renderer.Write(fencedCodeBlock.FencedChar, fencedCharCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -12,22 +12,27 @@ namespace Markdig.Renderers.Normalize;
|
||||
/// <seealso cref="NormalizeObjectRenderer{HeadingBlock}" />
|
||||
public class HeadingRenderer : NormalizeObjectRenderer<HeadingBlock>
|
||||
{
|
||||
private static readonly string[] HeadingTexts = {
|
||||
private static readonly string[] HeadingTexts = [
|
||||
"#",
|
||||
"##",
|
||||
"###",
|
||||
"####",
|
||||
"#####",
|
||||
"######",
|
||||
};
|
||||
];
|
||||
|
||||
protected override void Write(NormalizeRenderer renderer, HeadingBlock obj)
|
||||
{
|
||||
var headingText = obj.Level > 0 && obj.Level <= 6
|
||||
? HeadingTexts[obj.Level - 1]
|
||||
: new string('#', obj.Level);
|
||||
{
|
||||
if (obj.Level is > 0 and <= 6)
|
||||
{
|
||||
renderer.Write(HeadingTexts[obj.Level - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write('#', obj.Level);
|
||||
}
|
||||
|
||||
renderer.Write(headingText).Write(' ');
|
||||
renderer.Write(' ');
|
||||
renderer.WriteLeafInline(obj);
|
||||
|
||||
renderer.FinishBlock(renderer.Options.EmptyLineAfterHeading);
|
||||
|
||||
@@ -31,8 +31,8 @@ public class CodeInlineRenderer : NormalizeObjectRenderer<CodeInline>
|
||||
if (delimiterCount < count)
|
||||
delimiterCount = count;
|
||||
}
|
||||
var delimiterRun = new string(obj.Delimiter, delimiterCount + 1);
|
||||
renderer.Write(delimiterRun);
|
||||
|
||||
renderer.Write(obj.Delimiter, delimiterCount + 1);
|
||||
if (content.Length != 0)
|
||||
{
|
||||
if (content[0] == obj.Delimiter)
|
||||
@@ -49,6 +49,6 @@ public class CodeInlineRenderer : NormalizeObjectRenderer<CodeInline>
|
||||
{
|
||||
renderer.Write(' ');
|
||||
}
|
||||
renderer.Write(delimiterRun);
|
||||
renderer.Write(obj.Delimiter, delimiterCount + 1);
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,8 @@ public class EmphasisInlineRenderer : NormalizeObjectRenderer<EmphasisInline>
|
||||
{
|
||||
protected override void Write(NormalizeRenderer renderer, EmphasisInline obj)
|
||||
{
|
||||
var emphasisText = new string(obj.DelimiterChar, obj.DelimiterCount);
|
||||
renderer.Write(emphasisText);
|
||||
renderer.Write(obj.DelimiterChar, obj.DelimiterCount);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write(emphasisText);
|
||||
renderer.Write(obj.DelimiterChar, obj.DelimiterCount);
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@ public class CodeBlockRenderer : RoundtripObjectRenderer<CodeBlock>
|
||||
if (obj is FencedCodeBlock fencedCodeBlock)
|
||||
{
|
||||
renderer.Write(obj.TriviaBefore);
|
||||
var opening = new string(fencedCodeBlock.FencedChar, fencedCodeBlock.OpeningFencedCharCount);
|
||||
renderer.Write(opening);
|
||||
renderer.Write(fencedCodeBlock.FencedChar, fencedCodeBlock.OpeningFencedCharCount);
|
||||
|
||||
if (!fencedCodeBlock.TriviaAfterFencedChar.IsEmpty)
|
||||
{
|
||||
@@ -56,9 +55,8 @@ public class CodeBlockRenderer : RoundtripObjectRenderer<CodeBlock>
|
||||
renderer.WriteLeafRawLines(obj);
|
||||
|
||||
renderer.Write(fencedCodeBlock.TriviaBeforeClosingFence);
|
||||
var closing = new string(fencedCodeBlock.FencedChar, fencedCodeBlock.ClosingFencedCharCount);
|
||||
renderer.Write(closing);
|
||||
if (!string.IsNullOrEmpty(closing))
|
||||
renderer.Write(fencedCodeBlock.FencedChar, fencedCodeBlock.ClosingFencedCharCount);
|
||||
if (fencedCodeBlock.ClosingFencedCharCount > 0)
|
||||
{
|
||||
// See example 207: "> ```\nfoo\n```"
|
||||
renderer.WriteLine(obj.NewLine);
|
||||
|
||||
@@ -12,14 +12,14 @@ namespace Markdig.Renderers.Roundtrip;
|
||||
/// <seealso cref="RoundtripObjectRenderer{HeadingBlock}" />
|
||||
public class HeadingRenderer : RoundtripObjectRenderer<HeadingBlock>
|
||||
{
|
||||
private static readonly string[] HeadingTexts = {
|
||||
private static readonly string[] HeadingTexts = [
|
||||
"#",
|
||||
"##",
|
||||
"###",
|
||||
"####",
|
||||
"#####",
|
||||
"######",
|
||||
};
|
||||
];
|
||||
|
||||
protected override void Write(RoundtripRenderer renderer, HeadingBlock obj)
|
||||
{
|
||||
@@ -28,12 +28,11 @@ public class HeadingRenderer : RoundtripObjectRenderer<HeadingBlock>
|
||||
renderer.RenderLinesBefore(obj);
|
||||
|
||||
var headingChar = obj.Level == 1 ? '=' : '-';
|
||||
var line = new string(headingChar, obj.HeaderCharCount);
|
||||
|
||||
renderer.WriteLeafInline(obj);
|
||||
renderer.WriteLine(obj.SetextNewline);
|
||||
renderer.Write(obj.TriviaBefore);
|
||||
renderer.Write(line);
|
||||
renderer.Write(headingChar, obj.HeaderCharCount);
|
||||
renderer.WriteLine(obj.NewLine);
|
||||
renderer.Write(obj.TriviaAfter);
|
||||
|
||||
@@ -43,12 +42,17 @@ public class HeadingRenderer : RoundtripObjectRenderer<HeadingBlock>
|
||||
{
|
||||
renderer.RenderLinesBefore(obj);
|
||||
|
||||
var headingText = obj.Level > 0 && obj.Level <= 6
|
||||
? HeadingTexts[obj.Level - 1]
|
||||
: new string('#', obj.Level);
|
||||
|
||||
renderer.Write(obj.TriviaBefore);
|
||||
renderer.Write(headingText);
|
||||
|
||||
if (obj.Level is > 0 and <= 6)
|
||||
{
|
||||
renderer.Write(HeadingTexts[obj.Level - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.Write('#', obj.Level);
|
||||
}
|
||||
|
||||
renderer.Write(obj.TriviaAfterAtxHeaderChar);
|
||||
renderer.WriteLeafInline(obj);
|
||||
renderer.Write(obj.TriviaAfter);
|
||||
|
||||
@@ -14,12 +14,11 @@ public class CodeInlineRenderer : RoundtripObjectRenderer<CodeInline>
|
||||
{
|
||||
protected override void Write(RoundtripRenderer renderer, CodeInline obj)
|
||||
{
|
||||
var delimiterRun = new string(obj.Delimiter, obj.DelimiterCount);
|
||||
renderer.Write(delimiterRun);
|
||||
renderer.Write(obj.Delimiter, obj.DelimiterCount);
|
||||
if (!obj.ContentSpan.IsEmpty)
|
||||
{
|
||||
renderer.Write(obj.ContentWithTrivia);
|
||||
}
|
||||
renderer.Write(delimiterRun);
|
||||
renderer.Write(obj.Delimiter, obj.DelimiterCount);
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,8 @@ public class EmphasisInlineRenderer : RoundtripObjectRenderer<EmphasisInline>
|
||||
{
|
||||
protected override void Write(RoundtripRenderer renderer, EmphasisInline obj)
|
||||
{
|
||||
var emphasisText = new string(obj.DelimiterChar, obj.DelimiterCount);
|
||||
renderer.Write(emphasisText);
|
||||
renderer.Write(obj.DelimiterChar, obj.DelimiterCount);
|
||||
renderer.WriteChildren(obj);
|
||||
renderer.Write(emphasisText);
|
||||
renderer.Write(obj.DelimiterChar, obj.DelimiterCount);
|
||||
}
|
||||
}
|
||||
@@ -211,6 +211,25 @@ public abstract class TextRendererBase<T> : TextRendererBase where T : TextRende
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified char repeated a specified number of times.
|
||||
/// </summary>
|
||||
/// <param name="c">The char to write.</param>
|
||||
/// <param name="count">The number of times to write the char.</param>
|
||||
/// <returns>This instance</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal T Write(char c, int count)
|
||||
{
|
||||
WriteIndent();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Writer.Write(c);
|
||||
}
|
||||
|
||||
return (T)this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes the specified slice.
|
||||
/// </summary>
|
||||
|
||||
@@ -21,7 +21,7 @@ public class CodeBlock : LeafBlock
|
||||
}
|
||||
|
||||
private List<CodeBlockLine>? _codeBlockLines;
|
||||
public List<CodeBlockLine> CodeBlockLines => _codeBlockLines ??= new();
|
||||
public List<CodeBlockLine> CodeBlockLines => _codeBlockLines ??= [];
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CodeBlock"/> class.
|
||||
|
||||
@@ -27,7 +27,7 @@ public abstract class ContainerBlock : Block, IList<Block>, IReadOnlyList<Block>
|
||||
/// <param name="parser">The parser used to create this block.</param>
|
||||
protected ContainerBlock(BlockParser? parser) : base(parser)
|
||||
{
|
||||
_children = Array.Empty<BlockWrapper>();
|
||||
_children = [];
|
||||
SetTypeKind(isInline: false, isContainer: true);
|
||||
}
|
||||
|
||||
@@ -301,14 +301,9 @@ public abstract class ContainerBlock : Block, IList<Block>, IReadOnlyList<Block>
|
||||
|
||||
#endregion
|
||||
|
||||
private sealed class BlockComparisonWrapper : IComparer<BlockWrapper>
|
||||
private sealed class BlockComparisonWrapper(Comparison<Block> comparison) : IComparer<BlockWrapper>
|
||||
{
|
||||
private readonly Comparison<Block> _comparison;
|
||||
|
||||
public BlockComparisonWrapper(Comparison<Block> comparison)
|
||||
{
|
||||
_comparison = comparison;
|
||||
}
|
||||
private readonly Comparison<Block> _comparison = comparison;
|
||||
|
||||
public int Compare(BlockWrapper x, BlockWrapper y)
|
||||
{
|
||||
@@ -316,14 +311,9 @@ public abstract class ContainerBlock : Block, IList<Block>, IReadOnlyList<Block>
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class BlockComparerWrapper : IComparer<BlockWrapper>
|
||||
private sealed class BlockComparerWrapper(IComparer<Block> comparer) : IComparer<BlockWrapper>
|
||||
{
|
||||
private readonly IComparer<Block> _comparer;
|
||||
|
||||
public BlockComparerWrapper(IComparer<Block> comparer)
|
||||
{
|
||||
_comparer = comparer;
|
||||
}
|
||||
private readonly IComparer<Block> _comparer = comparer;
|
||||
|
||||
public int Compare(BlockWrapper x, BlockWrapper y)
|
||||
{
|
||||
|
||||
@@ -155,16 +155,10 @@ public abstract class MarkdownObject : IMarkdownObject
|
||||
|
||||
private class DataEntriesAndTrivia
|
||||
{
|
||||
private struct DataEntry
|
||||
private struct DataEntry(object key, object value)
|
||||
{
|
||||
public readonly object Key;
|
||||
public object Value;
|
||||
|
||||
public DataEntry(object key, object value)
|
||||
{
|
||||
Key = key;
|
||||
Value = value;
|
||||
}
|
||||
public readonly object Key = key;
|
||||
public object Value = value;
|
||||
}
|
||||
|
||||
private DataEntry[]? _entries;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class QuoteBlock : ContainerBlock
|
||||
public class QuoteBlockLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets trivia occuring before the first quote character.
|
||||
/// Gets or sets trivia occurring before the first quote character.
|
||||
/// </summary>
|
||||
public StringSlice TriviaBefore { get; set; }
|
||||
|
||||
|
||||
@@ -37,26 +37,26 @@ public struct SourceSpan : IEquatable<SourceSpan>
|
||||
/// <summary>
|
||||
/// Gets the character length of this element within the original source code.
|
||||
/// </summary>
|
||||
public int Length => End - Start + 1;
|
||||
public readonly int Length => End - Start + 1;
|
||||
|
||||
public bool IsEmpty => Start > End;
|
||||
public readonly bool IsEmpty => Start > End;
|
||||
|
||||
public SourceSpan MoveForward(int count)
|
||||
{
|
||||
return new SourceSpan(Start + count, End + count);
|
||||
}
|
||||
|
||||
public bool Equals(SourceSpan other)
|
||||
public readonly bool Equals(SourceSpan other)
|
||||
{
|
||||
return Start == other.Start && End == other.End;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
public override readonly bool Equals(object? obj)
|
||||
{
|
||||
return obj is SourceSpan sourceSpan && Equals(sourceSpan);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
public override readonly int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
@@ -74,7 +74,7 @@ public struct SourceSpan : IEquatable<SourceSpan>
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
public override readonly string ToString()
|
||||
{
|
||||
return $"{Start}-{End}";
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
Reference in New Issue
Block a user