diff --git a/Readme.md b/Readme.md index 982c1a2..ada394c 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,6 @@ # MarkdigToc [![NuGet](https://img.shields.io/nuget/v/Leisn.MarkdigToc)](https://www.nuget.org/packages/Leisn.MarkdigToc/) [![NuGet](https://img.shields.io/nuget/v/Leisn.MarkdigToc.Signed)](https://www.nuget.org/packages/Leisn.MarkdigToc.Signed/) -MarkdigToc is a extension for [Markdig](https://github.com/xoofx/markdig) to generate table of content by parse [toc] in markdown document. +MarkdigToc is a extension for [Markdig](https://github.com/xoofx/markdig) to generate table of content by parse `[toc]` or `[[_toc_]]` in markdown document. > Currently just for render to html. @@ -23,6 +23,16 @@ var result=Markdown.ToHtml(@" ## t1.2 "); Console.WriteLine(result); + +var result2=Markdown.ToHtml(@" +[[_TOC_]] +# t1 +## t1.1 +### t1.1.1 +### t1.1.2 +## t1.2 +"); +Console.WriteLine(result); ``` Use with custom options: diff --git a/Tests/RendererTest.cs b/Tests/RendererTest.cs index 4780203..8df6868 100644 --- a/Tests/RendererTest.cs +++ b/Tests/RendererTest.cs @@ -44,11 +44,11 @@ public void MdFilesTest() var md = File.ReadAllText(item + ".md"); var lintActual = Markdown.ToHtml(md, lintPipeline); var lintExpected = File.ReadAllText(item + "-lint.html"); - Assert.AreEqual(lintExpected, lintActual, $"Failed lint :{item}"); + Assert.AreEqual(lintExpected.ReplaceLineEndings(), lintActual.ReplaceLineEndings(), $"Failed lint :{item}"); var noLintActual = Markdown.ToHtml(md, noLintPipelint); var noLintExpected = File.ReadAllText(item + "-nolint.html"); - Assert.AreEqual(noLintExpected, noLintActual, $"Failed nolint :{item}"); + Assert.AreEqual(noLintExpected.ReplaceLineEndings(), noLintActual.ReplaceLineEndings(), $"Failed nolint :{item}"); } } diff --git a/Tests/TestFiles/alternate-lint.html b/Tests/TestFiles/alternate-lint.html new file mode 100644 index 0000000..dc4f9f8 --- /dev/null +++ b/Tests/TestFiles/alternate-lint.html @@ -0,0 +1,16 @@ + +

t1

+

t1.1

+

1.2

+

t2

+

t2.1

+

t2.1.1

+

t2.1.2

+

t2.1.3

+

t2.2

+

t3

+

t3.1

+

t3.2

+

t3.2.1

+

t3.2.2

+

t4

diff --git a/Tests/TestFiles/alternate-nolint.html b/Tests/TestFiles/alternate-nolint.html new file mode 100644 index 0000000..529e8c3 --- /dev/null +++ b/Tests/TestFiles/alternate-nolint.html @@ -0,0 +1,16 @@ + +

t1

+

t1.1

+

1.2

+

t2

+

t2.1

+

t2.1.1

+

t2.1.2

+

t2.1.3

+

t2.2

+

t3

+

t3.1

+

t3.2

+

t3.2.1

+

t3.2.2

+

t4

diff --git a/Tests/TestFiles/alternate.md b/Tests/TestFiles/alternate.md new file mode 100644 index 0000000..4fbee74 --- /dev/null +++ b/Tests/TestFiles/alternate.md @@ -0,0 +1,34 @@ +[[_TOC_]] + + + +# t1 + +## t1.1 + +## 1.2 + +# t2 + +## t2.1 + +### t2.1.1 + +### t2.1.2 + +### t2.1.3 + +## t2.2 + +# t3 + +## t3.1 + +## t3.2 + +### t3.2.1 + +### t3.2.2 + +# t4 + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 9e8da57..0837fd2 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net9.0 false diff --git a/src/TocBlockParser.cs b/src/TocBlockParser.cs index 8e92473..adde5ed 100644 --- a/src/TocBlockParser.cs +++ b/src/TocBlockParser.cs @@ -17,7 +17,7 @@ public TocBlockParser(TocOptions options) OpeningCharacters = new[] { '[' }; } - const string TOC = "[toc]"; + readonly string[] TOCTags = { "[toc]", "[[_toc_]]" }; public override BlockState TryOpen(BlockProcessor processor) { if (processor.IsCodeIndent) @@ -26,50 +26,56 @@ public override BlockState TryOpen(BlockProcessor processor) var column = processor.Column; var sourcePosition = line.Start; - var match = line.MatchLowercase(TOC); - if (!match) - return BlockState.None; + foreach (var toc in TOCTags) + { + var match = line.MatchLowercase(toc); + if (!match) + continue; - var c = line.CurrentChar; - for (int i = 0; i < TOC.Length; i++) - c = processor.NextChar(); + var c = line.CurrentChar; + for (int i = 0; i < toc.Length; i++) + c = processor.NextChar(); - StringSlice trivia = StringSlice.Empty; - if (processor.TrackTrivia && c.IsSpaceOrTab()) - { - trivia = new StringSlice(processor.Line.Text, processor.Start, processor.Start); - processor.NextChar(); - } + StringSlice trivia = StringSlice.Empty; + if (processor.TrackTrivia && c.IsSpaceOrTab()) + { + trivia = new StringSlice(processor.Line.Text, processor.Start, processor.Start); + processor.NextChar(); + } - var block = new TocBlock(this) - { - Column = column, - Span = { Start = sourcePosition }, - TriviaAfterAtxHeaderChar = trivia, - TriviaBefore = processor.UseTrivia(sourcePosition - 1), - LinesBefore = processor.LinesBefore, - NewLine = processor.Line.NewLine, - }; - processor.LinesBefore = null; + var block = new TocBlock(this) + { + Column = column, + Span = { Start = sourcePosition }, + TriviaAfterAtxHeaderChar = trivia, + TriviaBefore = processor.UseTrivia(sourcePosition - 1), + LinesBefore = processor.LinesBefore, + NewLine = processor.Line.NewLine, + }; + processor.LinesBefore = null; - processor.NewBlocks.Push(block); - if (!processor.TrackTrivia) - { - processor.GoToColumn(column + TOC.Length + 1); - } - TryParseAttributes?.Invoke(processor, ref processor.Line, block); + processor.NewBlocks.Push(block); + if (!processor.TrackTrivia) + { + processor.GoToColumn(column + toc.Length + 1); + } - block.Span.End = processor.Line.End; + TryParseAttributes?.Invoke(processor, ref processor.Line, block); - if (processor.TrackTrivia) - { - var wsa = new StringSlice(processor.Line.Text, processor.Line.End + 1, processor.Line.End); - block.TriviaAfter = wsa; - if (wsa.Overlaps(block.TriviaAfterAtxHeaderChar)) - block.TriviaAfter = StringSlice.Empty; + block.Span.End = processor.Line.End; + + if (processor.TrackTrivia) + { + var wsa = new StringSlice(processor.Line.Text, processor.Line.End + 1, processor.Line.End); + block.TriviaAfter = wsa; + if (wsa.Overlaps(block.TriviaAfterAtxHeaderChar)) + block.TriviaAfter = StringSlice.Empty; + } + + return BlockState.Break; } - return BlockState.Break; + return BlockState.None; } public override bool Close(BlockProcessor processor, Block block)