-
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
Сазонов Александр #233
base: master
Are you sure you want to change the base?
Сазонов Александр #233
Changes from 7 commits
ee8842e
f19c836
cd5dc04
be46adb
79d1e65
e149587
f8e12c2
dc503e0
aee3615
c17136a
3bbe844
f1068d7
fd6a1a0
4a6be5d
f0429ab
65119ec
64c2a3f
e9f8459
1867fad
0c49358
1e36da5
7955386
5090645
6bf34a4
4ed3d1f
288342e
4a64ed2
e38afe3
a176465
ff1b502
4a8f2b4
498c754
5d67ab8
ee04ac4
f921258
3fb6a79
80fcee3
f8f5d84
93a160f
954e5c0
b66c900
d13d24a
751f4ff
e455978
c59dd5e
1aadbc9
91dd8ad
04644f3
4de72d8
dacaa2c
4f087ad
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,11 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Html; | ||
|
||
public class BoldTag : IHtmlTag | ||
{ | ||
public Token ToHtml(string value) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Html; | ||
|
||
public class HeaderTag : IHtmlTag | ||
{ | ||
public Token ToHtml(string value) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Html; | ||
|
||
public interface IHtmlTag | ||
{ | ||
Token ToHtml(string value); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Html; | ||
|
||
public class ItalicTag : IHtmlTag | ||
{ | ||
public Token ToHtml(string value) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} |
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,16 @@ | ||
using Markdown.Renderers; | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown; | ||
|
||
public class Md | ||
{ | ||
private readonly IRenderer _renderer = new HtmlRenderer(); | ||
private readonly MarkdownTokenParser _tokenParser = new(); | ||
|
||
public string Render(string text) | ||
{ | ||
var tokens = _tokenParser.Parse(text); | ||
return _renderer.Render(tokens); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Renderers; | ||
|
||
public class HtmlRenderer : IRenderer | ||
{ | ||
public string Render(IEnumerable<Token> tokens) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
using Markdown.Tokens; | ||
|
||
namespace Markdown.Renderers; | ||
public interface IRenderer | ||
{ | ||
string Render(IEnumerable<Token> document); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using Markdown.Html; | ||
|
||
namespace Markdown.Tokens; | ||
|
||
public class MarkdownTokenParser | ||
{ | ||
private readonly Dictionary<string, IHtmlTag> _markdownTags = new() | ||
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. А правда, что |
||
{ | ||
{"_", new ItalicTag()}, | ||
{"__", new BoldTag()}, | ||
{"#", new HeaderTag()} | ||
}; | ||
|
||
public IEnumerable<Token> Parse(string text) | ||
{ | ||
var lines = SplitIntoLines(text); | ||
return ParseLines(lines); | ||
} | ||
|
||
private static string[] SplitIntoLines(string text) | ||
{ | ||
return text.Split(['\n', '\r']); | ||
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. Не успел настроить Rider, а VS не дает такие подсказки=) |
||
} | ||
|
||
private IEnumerable<Token> ParseLines(string[] lines) | ||
{ | ||
foreach (var line in lines) | ||
{ | ||
foreach (var token in ParseLine(line)) | ||
{ | ||
yield return token; | ||
} | ||
yield return CreateNewLineToken(); | ||
} | ||
} | ||
|
||
private IEnumerable<Token> ParseLine(string line) | ||
{ | ||
var words = SplitIntoWords(line); | ||
foreach (var word in words) | ||
{ | ||
yield return ParseWord(word); | ||
yield return CreateSpaceToken(); | ||
} | ||
} | ||
|
||
private static string[] SplitIntoWords(string line) | ||
{ | ||
return line.Split(); | ||
} | ||
|
||
private Token ParseWord(string word) | ||
{ | ||
return TryParseMarkdownTag(word, out var token) | ||
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. Думаю, что сплит по пробелам лишний. Строку буду парсить на токены. |
||
? token | ||
: CreateTextToken(word); | ||
} | ||
|
||
private bool TryParseMarkdownTag(string value, out Token token) | ||
{ | ||
token = CreateTextToken(value); | ||
|
||
var matchingTag = FindMatchingTag(value); | ||
if (matchingTag == null) | ||
return false; | ||
|
||
token = matchingTag.ToHtml(value); | ||
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.
Или я не понял твою мысль |
||
return true; | ||
} | ||
|
||
private IHtmlTag? FindMatchingTag(string value) | ||
{ | ||
return _markdownTags | ||
.Where(tag => value.StartsWith(tag.Key)) | ||
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. Такие поиски точно закроют все-все потребности конвертации? |
||
.Select(tag => tag.Value) | ||
.FirstOrDefault(); | ||
} | ||
|
||
private static Token CreateTextToken(string value) | ||
{ | ||
return new Token(value, TokenType.Text); | ||
} | ||
|
||
private static Token CreateSpaceToken() | ||
{ | ||
return new Token(" ", TokenType.Space); | ||
} | ||
|
||
private static Token CreateNewLineToken() | ||
{ | ||
return new Token("\n", TokenType.NewLine); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
namespace Markdown.Tokens; | ||
|
||
public class Token(string content, TokenType type); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
namespace Markdown.Tokens; | ||
|
||
public enum TokenType | ||
{ | ||
Tag, | ||
Text, | ||
NewLine, | ||
Space | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Markdown | ||
|
||
Напиши процессор упрощённого markdown-подобного языка разметки. | ||
|
||
[Спецификация языка разметки](MarkdownSpec.md). | ||
|
||
## Формат | ||
|
||
В fork-е этого репозитория создай проект Markdown и реализуй метод Render класса Md. Он принимает в качестве аргумента текст в markdown-подобной разметке, и возвращает строку с html-кодом этого текста согласно спецификации. | ||
|
||
Обрати внимание, что в этой задаче <ins>запрещено</ins> использовать регулярные выражения. | ||
|
||
## Важные моменты | ||
1. Проведи начальное проектирование: зафиксируй классы и их методы в коде (а также связи между классами), но не пиши внутренности методов | ||
2. Покажи декомпозицию наставнику, получи обратную связь | ||
3. После этого приступай к реализации методов, используя TDD | ||
4. Помни, твой алгоритм должен работать быстро — линейно или почти линейно от размера входа. Не забудь написать такой тест! | ||
|
||
## Оценка | ||
|
||
#### Минимальные требования (на 1 балл) | ||
1. Поддерживаются тэги `_`, `__` и `#` согласно спецификации | ||
2. Тесты | ||
|
||
#### Полное решение (на 2 балла) | ||
1. Выполнены минимальные требования | ||
2. Решение разбито на составные части, каждая из которых легко читается | ||
|
||
#### Максимальное решение (на 3 балла) | ||
1. Выполнено полное решение | ||
2. Умеет рендериться <ins>один</ins> из дополнительных тегов: | ||
- Маркерованный список | ||
- Нумерованный список | ||
- Ссылка | ||
- Картинка | ||
3. В файле [спецификации](MarkdownSpec.md) подробно описано, как работает новый тег | ||
4. Обрати внимание: если упадет читаемость кода, то дополнительный балл засчитан не будет! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Спецификация языка разметки | ||
|
||
Посмотрите этот файл в сыром виде. Сравните с тем, что показывает github. | ||
Все совпадения случайны ;) | ||
|
||
|
||
|
||
# Курсив | ||
|
||
Текст, _окруженный с двух сторон_ одинарными символами подчерка, | ||
должен помещаться в HTML-тег \<еm> вот так: | ||
|
||
Текст, \<еm>окруженный с двух сторон\</еm> одинарными символами подчерка, | ||
должен помещаться в HTML-тег \<еm>. | ||
|
||
|
||
|
||
# Полужирный | ||
|
||
__Выделенный двумя символами текст__ должен становиться полужирным с помощью тега \<strоng>. | ||
|
||
|
||
|
||
# Экранирование | ||
|
||
Любой символ можно экранировать, чтобы он не считался частью разметки. | ||
\_Вот это\_, не должно выделиться тегом \<еm>. | ||
|
||
Символ экранирования исчезает из результата, только если экранирует что-то. | ||
Здесь сим\волы экранирования\ \должны остаться.\ | ||
|
||
Символ экранирования тоже можно экранировать: \\_вот это будет выделено тегом_ \<еm> | ||
|
||
|
||
|
||
# Взаимодействие тегов | ||
|
||
Внутри __двойного выделения _одинарное_ тоже__ работает. | ||
|
||
Но не наоборот — внутри _одинарного __двойное__ не_ работает. | ||
|
||
Подчерки внутри текста c цифрами_12_3 не считаются выделением и должны оставаться символами подчерка. | ||
|
||
Однако выделять часть слова они могут: и в _нач_але, и в сер_еди_не, и в кон_це._ | ||
|
||
В то же время выделение в ра_зных сл_овах не работает. | ||
|
||
__Непарные_ символы в рамках одного абзаца не считаются выделением. | ||
|
||
За подчерками, начинающими выделение, должен следовать непробельный символ. Иначе эти_ подчерки_ не считаются выделением | ||
и остаются просто символами подчерка. | ||
|
||
Подчерки, заканчивающие выделение, должны следовать за непробельным символом. Иначе эти _подчерки _не считаются_ окончанием выделения | ||
и остаются просто символами подчерка. | ||
|
||
В случае __пересечения _двойных__ и одинарных_ подчерков ни один из них не считается выделением. | ||
|
||
Если внутри подчерков пустая строка ____, то они остаются символами подчерка. | ||
|
||
|
||
|
||
# Заголовки | ||
|
||
Абзац, начинающийся с "# ", выделяется тегом \<h1> в заголовок. | ||
В тексте заголовка могут присутствовать все прочие символы разметки с указанными правилами. | ||
|
||
Таким образом | ||
|
||
# Заголовок __с _разными_ символами__ | ||
|
||
превратится в: | ||
|
||
\<h1>Заголовок \<strоng>с \<еm>разными\</еm> символами\</strоng>\</h1> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
|
||
<IsPackable>false</IsPackable> | ||
<IsTestProject>true</IsTestProject> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
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. Все еще есть лишние подключения) |
||
<PackageReference Include="FluentAssertions" Version="6.12.2" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="NUnit" Version="3.14.0" /> | ||
<PackageReference Include="NUnit.Analyzers" Version="3.9.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Markdown\Markdown.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Using Include="NUnit.Framework" /> | ||
</ItemGroup> | ||
|
||
</Project> |
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.
Посмотрел решение в целом - пока не понимаю, будет ли оно работать вообще или нет. Подход со стороны "от общего к частному" - супер, но вот по текущему проектированию у меня не сложилось понимание, как будут закрываться на 2 и 3 балла задания