-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Попов Захар #235
base: master
Are you sure you want to change the base?
Попов Захар #235
Changes from 1 commit
f53e022
f8768e2
476d331
36691f2
f04e7fe
a0e7f63
f99e193
f0948eb
1bfdc4a
058c67f
c166721
1835148
7b04aad
e7e24a7
d7acd5a
b176806
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Converters | ||
{ | ||
internal interface IConverter | ||
{ | ||
IList<Token> Convert(IList<Token> tokensToConvert); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using Markdown.Tags; | ||
using Markdown.Tokens; | ||
using Markdown.Tags.HTMLTags; | ||
|
||
namespace Markdown.Converters.MdToHTMLConverters | ||
{ | ||
internal class ConverterMdToHTML : IConverter | ||
{ | ||
private readonly Dictionary<string, ITag> _mdTagNamesToHTMLTags | ||
= new Dictionary<string, ITag>() | ||
{ | ||
{"_", new HTMLTag("em") }, | ||
{"__", new HTMLTag("strong") }, | ||
{"# ", new HTMLTag("h1") }, | ||
}; | ||
|
||
public IList<Token> Convert(IList<Token> tokensToConvert) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using Markdown.Converters; | ||
using Markdown.Parsers; | ||
using Markdown.Writers; | ||
|
||
namespace Markdown | ||
{ | ||
internal class Md(IParser parser, IConverter converter, IWriter writer) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это хорошо, что класс Нужно оставить только минимально необходимый набор параметров, которые должны быть получены извне. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
private readonly IParser _parser = parser; | ||
private readonly IConverter _converter = converter; | ||
private readonly IWriter _writer = writer; | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public string Render(string text) | ||
{ | ||
var mdTokens = _parser.ParseToTokens(text); | ||
|
||
var HTMLTokens = _converter.Convert(mdTokens); | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return _writer.Write(HTMLTokens); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Parsers | ||
{ | ||
internal interface IParser | ||
{ | ||
IList<Token> ParseToTokens(string textToParse); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using Markdown.Tags; | ||
using Markdown.Tags.MdTags; | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Parsers.MdParsers | ||
{ | ||
internal class ParserMD : IParser | ||
{ | ||
private readonly Dictionary<string, ITag> _mdTags = new Dictionary<string, ITag>() | ||
{ | ||
{"_", new PairedMdTag("_") }, | ||
{"__", new PairedMdTag("__") }, | ||
{"# ", new SingleMdTag("# ") } | ||
}; | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public IList<Token> ParseToTokens(string textToParse) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
using Markdown.Converters.MdToHTMLConverters; | ||
using Markdown.Parsers.MdParsers; | ||
using Markdown.Tags; | ||
using Markdown.Tags.HTMLTags; | ||
using Markdown.Tags.MdTags; | ||
using Markdown.Tokens; | ||
using Markdown.Writers; | ||
|
||
namespace Markdown | ||
{ | ||
internal class Program | ||
{ | ||
static void Main(string[] args) | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
var simpleText = "Hello, Andrey"; | ||
var simpleTokenMD = new SimpleStringToken(simpleText); | ||
var simpleTokenHTML = new SimpleStringToken("Hello, Andrey"); | ||
ShowEaxmple(simpleText, simpleTokenMD, simpleTokenHTML); | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
var markdownText = "_Hello, Andrey_"; | ||
var markdownTokenMD = new MarkdownStringToken(new PairedMdTag("_"), "Hello, Andrey"); | ||
var markdownTokenHTML = new MarkdownStringToken(new HTMLTag("em"), "Hello, Andrey"); | ||
ShowEaxmple(markdownText, markdownTokenMD, markdownTokenHTML); | ||
|
||
|
||
var complexText = "__с _разными_ символами__"; | ||
var complexInnerTokensMD = new List<Token>() | ||
{ | ||
new SimpleStringToken("c "), | ||
new MarkdownStringToken(new PairedMdTag("_"),"разными"), | ||
new SimpleStringToken(" символами") | ||
}; | ||
var complexInnerTokensHTML = new List<Token>() | ||
{ | ||
new SimpleStringToken("c "), | ||
new MarkdownStringToken(new HTMLTag("em"),"разными"), | ||
new SimpleStringToken(" символами") | ||
}; | ||
var complexTokenMD = new ComplexSringToken(new PairedMdTag("__"), complexInnerTokensMD); | ||
var complexTokenHTML = new ComplexSringToken(new HTMLTag("strong"), complexInnerTokensHTML); | ||
ShowEaxmple(complexText, complexTokenMD, complexTokenHTML); | ||
|
||
|
||
var complexHeaderText = "# Заголовок __с _разными_ символами__"; | ||
var complexHeaderInnerTokensMD = new List<Token>() | ||
{ | ||
new SimpleStringToken("Заголовок "), | ||
new ComplexSringToken(new PairedMdTag("__"), complexInnerTokensMD) | ||
}; | ||
var complexHeaderInnerTokensHTML = new List<Token>() | ||
{ | ||
new SimpleStringToken("Заголовок "), | ||
new ComplexSringToken(new HTMLTag("strong"), complexInnerTokensHTML) | ||
}; | ||
var complexHeaderTokenMD = new ComplexSringToken(new SingleMdTag("# "), complexHeaderInnerTokensMD); | ||
var complexHeaderTokenHTML = new ComplexSringToken(new HTMLTag("h1"), complexHeaderInnerTokensHTML); | ||
ShowEaxmple(complexHeaderText, complexHeaderTokenMD, complexHeaderTokenHTML); | ||
|
||
Console.ReadLine(); | ||
|
||
var exampleText = "# Заголовок __с _разными_ символами__"; | ||
var parser = new ParserMD(); | ||
var converter = new ConverterMdToHTML(); | ||
var writer = new WriterHTML(); | ||
var md = new Md(parser, converter, writer); | ||
var htmlCode = md.Render(exampleText); | ||
} | ||
|
||
private static void ShowEaxmple( | ||
string rawText, | ||
Token tokenMD, | ||
Token tokenHTML) | ||
{ | ||
Console.WriteLine("Пример:"); | ||
Console.WriteLine($"Переданный текст: {rawText}"); | ||
Console.WriteLine($"Востановленный из токена MD текст: {tokenMD}"); | ||
Console.WriteLine($"Востановленный из токена HTML текст: {tokenHTML}"); | ||
Console.WriteLine(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Markdown.Tags.HTMLTags | ||
{ | ||
internal class HTMLTag(string tagName) : Tag(tagName), ITag | ||
{ | ||
public string OpeningTagName => $"<{TagName}>"; | ||
|
||
public string ClosingTagName => $"</{TagName}>"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Markdown.Tags | ||
{ | ||
internal interface ITag | ||
{ | ||
string OpeningTagName { get; } | ||
string ClosingTagName { get; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Markdown.Tags.MdTags | ||
{ | ||
internal class PairedMdTag(string tagName) : Tag(tagName), ITag | ||
{ | ||
public string OpeningTagName => TagName; | ||
|
||
public string ClosingTagName => TagName; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Markdown.Tags.MdTags | ||
{ | ||
internal class SingleMdTag(string tagName) : Tag(tagName), ITag | ||
{ | ||
public string OpeningTagName => TagName; | ||
|
||
public string ClosingTagName => string.Empty; | ||
} | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace Markdown.Tags | ||
{ | ||
internal abstract class Tag | ||
{ | ||
protected Tag(string tagName) | ||
{ | ||
if (string.IsNullOrWhiteSpace(tagName)) | ||
{ | ||
throw new ArgumentException( | ||
"Имя тега не может быть null или пустой строкой"); | ||
} | ||
TagName = tagName; | ||
} | ||
public string TagName { get; } | ||
} | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using Markdown.Tags; | ||
using System.Text; | ||
|
||
namespace Markdown.Tokens | ||
{ | ||
internal class ComplexSringToken : Token | ||
{ | ||
public ITag Tag { get => _tag!; } | ||
public Token[] InnerTokens { get => _innerTokens!.ToArray(); } | ||
|
||
public ComplexSringToken(ITag tag, IList<Token> innerTokens) | ||
: base(tag: tag, innerTokens: innerTokens) | ||
{ | ||
if (tag is null) | ||
{ | ||
throw new ArgumentException("Передаваемый токен не может быть null"); | ||
} | ||
|
||
if (innerTokens is null) | ||
{ | ||
throw new ArgumentException("Передаваемые внутренние токены не могут быть null"); | ||
} | ||
|
||
if (innerTokens.Count == 0) | ||
{ | ||
throw new ArgumentException( | ||
"Передаваемые внутренние токены не могут быть пустыми"); | ||
} | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
var sb = new StringBuilder(); | ||
|
||
sb.Append(Tag.OpeningTagName); | ||
foreach (var token in InnerTokens) | ||
{ | ||
if (token is SimpleStringToken || token is MarkdownStringToken) | ||
{ | ||
sb.Append(token.ToString()); | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
continue; | ||
} | ||
sb.Append(token.ToString()); | ||
} | ||
sb.Append(Tag.ClosingTagName); | ||
|
||
return sb.ToString(); | ||
} | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using Markdown.Tags; | ||
|
||
namespace Markdown.Tokens | ||
{ | ||
internal class MarkdownStringToken : Token | ||
{ | ||
public ITag Tag { get => _tag!; } | ||
|
||
public string Content { get => _content!; } | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public MarkdownStringToken(ITag tag, string content) : base(tag: tag, content: content) | ||
{ | ||
if (tag is null) | ||
{ | ||
throw new ArgumentException("Передаваемый токен не может быть null"); | ||
} | ||
|
||
if (string.IsNullOrWhiteSpace(content)) | ||
{ | ||
throw new ArgumentException( | ||
"Содержимое токена не может быть null или пустой строкой"); | ||
} | ||
} | ||
|
||
public override string ToString() | ||
=> $"{Tag.OpeningTagName}{Content}{Tag.ClosingTagName}"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
namespace Markdown.Tokens | ||
{ | ||
internal class SimpleStringToken : Token | ||
{ | ||
public string Content { get => _content!; } | ||
|
||
public SimpleStringToken(string content) : base(content: content) | ||
{ | ||
if (string.IsNullOrWhiteSpace(content)) | ||
{ | ||
throw new ArgumentException( | ||
"Содержимое токена не может быть null или пустой строкой"); | ||
} | ||
} | ||
|
||
public override string ToString() => Content; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using Markdown.Tags; | ||
|
||
namespace Markdown.Tokens | ||
{ | ||
internal abstract class Token( | ||
ITag? tag = null, | ||
string? content = null, | ||
IList<Token>? innerTokens = null) | ||
{ | ||
protected readonly ITag? _tag = tag; | ||
protected readonly string? _content = content; | ||
protected readonly IList<Token>? _innerTokens = innerTokens; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Writers | ||
{ | ||
internal interface IWriter | ||
{ | ||
string Write(IList<Token> tokensToWrite); | ||
BlizPerfect marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Writers | ||
{ | ||
internal class WriterHTML : IWriter | ||
{ | ||
public string Write(IList<Token> tokensToWrite) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Добавлю тут про второй пункт из описания.
Если реализация у метода/класса одна, и в будущем не предвидится появление новых реализаций - то это можно реализовать статическим классом без дополнительного интерфейса.
Если же реализаций точно будет несколько, то в таком случае статика подойдёт тут в меньшей степени.
Нормально сделать интерфейс, который объявляет какие-либо методы и иметь динамические классы для него.
Что касается конкретно
IConverter
,IWriter
иIParser
, то наверное вопрос к тебе, что по твоему мнению никогда не потребует дополнительной реализации? А что может потребовать?