-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
kashin.aleksandr
committed
Dec 11, 2024
1 parent
6f02ada
commit abf4e24
Showing
37 changed files
with
242 additions
and
270 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
namespace Markdown; | ||
|
||
public interface IMarkdown | ||
public interface IMarkdownRenderer | ||
{ | ||
string Render(string markdown); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,31 @@ | ||
using Markdown.Render; | ||
using Markdown.Tokenizer; | ||
using Markdown.Tokenizer.Handlers; | ||
using Markdown.Tokenizer.Nodes; | ||
using Markdown.Tokenizer.Tags; | ||
using Markdown.TreeBuilder; | ||
|
||
namespace Markdown; | ||
|
||
public class MarkdownRenderer : IMarkdown | ||
public class MarkdownRenderer : IMarkdownRenderer | ||
{ | ||
private readonly ITreeRenderer treeRenderer = new TreeRenderer(); | ||
private readonly ITokenizer tokenizer; | ||
private readonly List<IHandler> handlers = new() | ||
{ | ||
new HeaderHandler(), | ||
new ItalicHandler(), | ||
new BoldHandler(), | ||
}; | ||
public string Render(string markdown) | ||
|
||
public MarkdownRenderer() | ||
{ | ||
var tokenizer = new MarkdownTokenizer(new HandlerManager(handlers), new TagProcessor()); | ||
var renderer = new HtmlRenderer(); | ||
var tokens = tokenizer.Tokenize(markdown); | ||
var tree = ToTree(tokens); | ||
return renderer.Render(tree); | ||
tokenizer = new MarkdownTokenizer(new HandlerManager(handlers), new TagProcessor()); | ||
} | ||
|
||
private Node ToTree(List<Token> tokens) | ||
public string Render(string markdown) | ||
{ | ||
Node mainNode = new MainNode(); | ||
Node currentNode = mainNode; | ||
for (int i = 0; i < tokens.Count; i++) | ||
{ | ||
if (tokens[i].TagStatus == TagStatus.Broken) | ||
{ | ||
currentNode.Children.Add(new TextNode{Value = tokens[i].Value}); | ||
continue; | ||
} | ||
|
||
if (tokens[i] is ItalicTag tag) | ||
{ | ||
if(tag.TagStatus == TagStatus.Open) | ||
{ | ||
var node = new ItalicNode(); | ||
currentNode.Children.Add(node); | ||
node.Parent = currentNode; | ||
currentNode = node; | ||
continue; | ||
} | ||
|
||
if (tag.TagStatus == TagStatus.Closed) | ||
{ | ||
currentNode = currentNode.Parent; | ||
continue; | ||
} | ||
} | ||
|
||
if (tokens[i] is BoldTag boldTag) | ||
{ | ||
if(boldTag.TagStatus == TagStatus.Open) | ||
{ | ||
var node = new BoldNode(); | ||
currentNode.Children.Add(node); | ||
node.Parent = currentNode; | ||
currentNode = node; | ||
continue; | ||
} | ||
|
||
if (boldTag.TagStatus == TagStatus.Closed) | ||
{ | ||
currentNode = currentNode.Parent; | ||
continue; | ||
} | ||
} | ||
|
||
if (tokens[i] is HeaderTag) | ||
{ | ||
var node = new HeaderNode(); | ||
currentNode.Children.Add(node); | ||
node.Parent = currentNode; | ||
currentNode = node; | ||
continue; | ||
} | ||
|
||
if (tokens[i] is NewLineToken) | ||
{ | ||
if (currentNode is HeaderNode) | ||
{ | ||
currentNode = currentNode.Parent; | ||
} | ||
continue; | ||
} | ||
|
||
if (tokens[i] is TextToken textToken) | ||
{ | ||
currentNode.Children.Add(new TextNode { Value = textToken.Value }); | ||
continue; | ||
} | ||
} | ||
var tokens = tokenizer.Tokenize(markdown); | ||
var tree = new TreeBuilder.TreeBuilder(new NodeFactory()).Build(tokens); | ||
|
||
return currentNode.Parent ?? currentNode; | ||
return treeRenderer.Render(tree); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using Markdown.TreeBuilder.Nodes; | ||
|
||
namespace Markdown.Render; | ||
|
||
public interface ITreeRenderer | ||
{ | ||
string Render(Node tokens); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,43 @@ | ||
namespace Markdown.Tests.Markdown; | ||
using NUnit.Framework; | ||
|
||
namespace Markdown.Tests.Markdown; | ||
|
||
[TestFixture] | ||
public class MarkdownTests | ||
{ | ||
private static readonly VerifySettings Settings = new(); | ||
private static readonly MarkdownRenderer Renderer = new(); | ||
private IMarkdownRenderer renderer; | ||
|
||
[OneTimeSetUp] | ||
public void OneTimeSetUp() | ||
[SetUp] | ||
public void SetUp() | ||
{ | ||
Settings.UseDirectory("snapshots"); | ||
renderer = new MarkdownRenderer(); | ||
} | ||
|
||
[TestCaseSource(nameof(ItalicTestCases))] | ||
public string Test_1(string input) => Renderer.Render(input); | ||
[TestCaseSource(nameof(MarkdownRendererTestCases))] | ||
public string MarkdownRenderer_Verify(string input) => renderer.Render(input); | ||
|
||
private static TestCaseData[] ItalicTestCases = | ||
private static TestCaseData[] MarkdownRendererTestCases = | ||
[ | ||
new TestCaseData("# Header").Returns("<h1>Header</h1>"), | ||
new TestCaseData("\\# Header").Returns("# Header"), | ||
new TestCaseData("\\\\# Header").Returns("\\<h1>Header</h1>"), | ||
new TestCaseData("_Italic text_").Returns("<em>Italic text</em>"), | ||
new TestCaseData("\\_Text_").Returns("_Text_"), | ||
new TestCaseData("\\\\_Italic text_").Returns("\\<em>Italic text</em>"), | ||
new TestCaseData("_Italic text").Returns("_Italic text"), | ||
new TestCaseData("Italic text_").Returns("Italic text_"), | ||
new TestCaseData("Italic_ text_").Returns("Italic_ text_"), | ||
new TestCaseData("_Italic _text").Returns("_Italic _text"), | ||
new TestCaseData("_нач_але").Returns("<em>нач</em>але"), | ||
new TestCaseData("сер_еди_не").Returns("сер<em>еди</em>не"), | ||
new TestCaseData("цифры_1_12_3").Returns("цифры_1_12_3"), | ||
new TestCaseData("кон_це._").Returns("кон<em>це.</em>"), | ||
new TestCaseData("в ра_зных сл_овах не").Returns("в ра_зных сл_овах не"), | ||
new TestCaseData("__bold__").Returns("<strong>bold</strong>"), | ||
new TestCaseData("_Text__").Returns("_Text__"), | ||
new TestCaseData("__Text_").Returns("__Text_"), | ||
new TestCaseData("__Italic __text").Returns("__Italic __text"), | ||
new TestCaseData("__два _один_ может__").Returns("<strong>два <em>один</em> может</strong>"), | ||
new TestCaseData("_одинарного __двойное__ не_").Returns( "<em>одинарного __двойное__ не</em>") | ||
new TestCaseData("# Header").Returns("<h1>Header</h1>").SetDescription("Простой заголовок."), | ||
new TestCaseData("\\# Header").Returns("# Header").SetDescription("Экранированный заголовок."), | ||
new TestCaseData("\\\\# Header").Returns("\\<h1>Header</h1>").SetDescription("Экранирован экранирования."), | ||
new TestCaseData("_Italic text_").Returns("<em>Italic text</em>").SetDescription("Курсив"), | ||
new TestCaseData("\\_Text_").Returns("_Text_").SetDescription("Экранирование курсива."), | ||
new TestCaseData("\\\\_Italic text_").Returns("\\<em>Italic text</em>").SetDescription("Экранирование экранирования курсива."), | ||
new TestCaseData("_Italic text").Returns("_Italic text").SetDescription("Одинокий открывающий тэг."), | ||
new TestCaseData("Italic text_").Returns("Italic text_").SetDescription("Одинокий закрывающий тэг."), | ||
new TestCaseData("Italic_ text_").Returns("Italic_ text_").SetDescription("Два закрывающих тэга."), | ||
new TestCaseData("_Italic _text").Returns("_Italic _text").SetDescription("Два открывающих тэга."), | ||
new TestCaseData("_нач_але").Returns("<em>нач</em>але").SetDescription("Курсив в начале слова."), | ||
new TestCaseData("сер_еди_не").Returns("сер<em>еди</em>не").SetDescription("Курсив в середине слова."), | ||
new TestCaseData("кон_це._").Returns("кон<em>це.</em>").SetDescription("Курсив в конце слова."), | ||
new TestCaseData("цифры_1_12_3").Returns("цифры_1_12_3").SetDescription("Между цифр - подчерки."), | ||
new TestCaseData("в ра_зных сл_овах не").Returns("в ра_зных сл_овах не").SetDescription("В разных словах - не работает."), | ||
new TestCaseData("__bold__").Returns("<strong>bold</strong>").SetDescription("Полужирный"), | ||
new TestCaseData("_Text__").Returns("_Text__").SetDescription("Разные тэги 1"), | ||
new TestCaseData("__Text_").Returns("__Text_").SetDescription("Разные тэги 2"), | ||
new TestCaseData("__Italic __text").Returns("__Italic __text").SetDescription("Два открывающих тэга."), | ||
new TestCaseData("__два _один_ может__").Returns("<strong>два <em>один</em> может</strong>").SetDescription("Курсив в полужирном."), | ||
new TestCaseData("_одинарного __двойное__ не_").Returns( "<em>одинарного __двойное__ не</em>").SetDescription("Полужирный в курсиве - не работает."), | ||
]; | ||
|
||
private static Task Verify(string target) => | ||
Verifier.Verify(target, Settings); | ||
|
||
[Test] | ||
public void SimpleText_Render_Verify() => | ||
Verify(Renderer.Render("Text")); | ||
|
||
[Test] | ||
public void EscapedCharacter_Render_Verify() => | ||
Verify(Renderer.Render(@"\_Text_")); | ||
|
||
[Test] | ||
public void ItalicText_Render_Verify() => | ||
Verify(Renderer.Render("_Italic text_")); | ||
|
||
[Test] | ||
public void BoldText_Render_Verify() => | ||
Verify(Renderer.Render("__Bold text__")); | ||
|
||
[Test] | ||
public void BoldWithItalicText_Render_Verify() => | ||
Verify(Renderer.Render("__Bold _with italic_ text__")); | ||
|
||
[Test] | ||
public void SimpleHeader_Render_Verify() => | ||
Verify(Renderer.Render("# Header")); | ||
|
||
[Test] | ||
public void TwoHeaders_Render_Verify() => | ||
Verify(Renderer.Render("# Header one \n# Header two")); | ||
// | ||
// [Test] | ||
// public void HeaderWithItalic_Render_Verify() => | ||
// Verify(Renderer.Render("# Header with _italic text_")); | ||
// | ||
// [Test] | ||
// public void HeaderWithBoldAndItalic_Render_Verify() => | ||
// Verify(Renderer.Render("# Header with _italic_ and __bold__ text")); | ||
// | ||
// [Test] | ||
// public void HeaderWithItalicInBold_Render_Verify() => | ||
// Verify(Renderer.Render("# Header ___italic_ in bold__ text")); | ||
// | ||
// [Test] | ||
// public void SimpleList_Render_Verify() => | ||
// Verify(Renderer.Render("- item1\n- item2")); | ||
// | ||
// [Test] | ||
// public void ListWithItalicAndBold_Render_Verify() => | ||
// Verify(Renderer.Render("- _item1_\n- __item2__")); | ||
} |
1 change: 0 additions & 1 deletion
1
cs/Markdown/Tests/Markdown/snapshots/MarkdownTests.SimpleHeader_Render_Verify.received.txt
This file was deleted.
Oops, something went wrong.
1 change: 0 additions & 1 deletion
1
cs/Markdown/Tests/Markdown/snapshots/MarkdownTests.SimpleHeader_Render_Verify.verified.txt
This file was deleted.
Oops, something went wrong.
1 change: 0 additions & 1 deletion
1
cs/Markdown/Tests/Markdown/snapshots/MarkdownTests.TwoHeaders_Render_Verify.received.txt
This file was deleted.
Oops, something went wrong.
1 change: 0 additions & 1 deletion
1
cs/Markdown/Tests/Markdown/snapshots/MarkdownTests.TwoHeaders_Render_Verify.verified.txt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.