-
Notifications
You must be signed in to change notification settings - Fork 319
Якшибаев Данил #255
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
Open
gogy4
wants to merge
33
commits into
kontur-courses:master
Choose a base branch
from
gogy4:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Якшибаев Данил #255
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
d37d48c
Провел проектирование, выделил интерфейсы с классами и extension мето…
gogy4 0739f53
изменить метод Wrap в зависимости от TokenType, провел небольшой рефа…
gogy4 3fb0ae8
Добавил новые токены, реализовал логику Tokenizer.cs и TagRender.cs
gogy4 c4a3f90
Перенес метод RenderLine в класс Render.cs и добавил некоторую логику…
gogy4 87a105f
Написал тесты, который проверяют логику работы рендера с _ и __. Поло…
gogy4 6c74bd6
Добавил тест на производительность
gogy4 8f77b1f
маленький рефакторинг
gogy4 4bece38
Добавил логику рендера для header. Написал тест для проверки новой ло…
gogy4 7c4967d
Сделал доп. класс для работы с тегами через стек
gogy4 818e646
Сделал классы, которые служат, только как данные рекордами. Добавил п…
gogy4 d2ef385
Убрал лишний таб в TagRender.cs. Вынес в отдельный статический класс …
gogy4 3dd1379
Порефакторил if, теперь все if начинаются с новой строки и скобок. Пе…
gogy4 2ca6b3f
Реализовал всю логику в Render.cs которая была описана на минимальный…
gogy4 d2b239c
Вынес логику проверки на закрытие тега в отдельный метод
gogy4 db6590b
Update MarkdownTests.cs
gogy4 cd9e0f4
Вынес новые enum для удобной работы с токенами. Сделал Token.cs и Tag…
gogy4 949c254
Merge remote-tracking branch 'origin/master'
gogy4 794afe9
Поменял логику в связи изменений дто
gogy4 b2d5fad
Переименовал класс рендера, вынес в отдельную логику работу с тегами,…
gogy4 78ccd27
Поменял тест, который проверяет работу за O(n), теперь выполняется не…
gogy4 5d37e7c
Добавил обработку нового тега - ссылки
gogy4 eb9d6b7
порефакторил код, добавил обработку ссылки, вынес повторяющийся код в…
gogy4 e62c0f0
Изменил текст в тестах, добавил новый тест
gogy4 f3157cf
Вынес работу с контентом в TagContext.cs, который реализует IDisposab…
gogy4 efc74a3
Допушил класс CharContext.cs
gogy4 0042b1f
Сделал обработку токенов через паттерн "Стратегия". Создал абстракцию…
gogy4 33ec3de
Применил паттерн "Стратегия" в TagProcessor.cs. Порефакторил классы.
gogy4 a95fcea
Небольшой рефактор теста Markdown_RenderTime_ShouldScaleLinearly
gogy4 fd494f6
Изменил MarkdownSpec.md
gogy4 4dbd8ac
Исправил MarkdownSpec.md
gogy4 bae770a
Исправил экранирование в MarkdownSpec.md
gogy4 f032539
Еще немного фиксов с экранированием
gogy4 49faf43
Фикс экранирования полужирного символа
gogy4 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,3 @@ | ||
| namespace Markdown.Dto; | ||
|
|
||
| public record CharContext(char? Next, bool CanOpen, bool CanClose); |
This file contains hidden or 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,46 @@ | ||
| using System.Text; | ||
|
|
||
| namespace Markdown.Dto | ||
| { | ||
| public class Tag | ||
| { | ||
| public Token Token { get; } | ||
| public StringBuilder Content { get; } | ||
| public bool IsOpen { get; } | ||
|
|
||
| public bool ContainsSpace { get; private set; } | ||
| public bool HasOnlyDigits { get; private set; } = true; | ||
|
|
||
| public Tag(Token token, StringBuilder content, bool isOpen) | ||
| { | ||
| Token = token; | ||
| Content = content; | ||
| IsOpen = isOpen; | ||
| UpdateFlags(content.ToString()); | ||
| } | ||
|
|
||
| public void Append(string text) | ||
| { | ||
| Content.Append(text); | ||
| UpdateFlags(text); | ||
| } | ||
|
|
||
| private void UpdateFlags(string text) | ||
| { | ||
| if (!ContainsSpace && text.Contains(' ')) | ||
| { | ||
| ContainsSpace = true; | ||
| } | ||
|
|
||
| if (!HasOnlyDigits) | ||
| { | ||
| return; | ||
| } | ||
| foreach (var ch in text.Skip(Token.Value.Length).Where(ch => !char.IsDigit(ch))) | ||
| { | ||
| HasOnlyDigits = false; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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,54 @@ | ||
| namespace Markdown.Dto | ||
| { | ||
| public class Token | ||
| { | ||
| public string Value { get; private set; } | ||
| public TokenType Type { get; private set; } | ||
| public TokenRole Role { get; private set; } | ||
| public TokenPosition Position { get; private set; } | ||
|
|
||
| public Token(string value, TokenType type, TokenRole role, TokenPosition position) | ||
| { | ||
| Value = value; | ||
| Type = type; | ||
| Role = role; | ||
| Position = position; | ||
| } | ||
|
|
||
| public Token(string value, TokenType type, bool canOpen, bool canClose) | ||
| { | ||
| Value = value; | ||
| Type = type; | ||
| DetermineRole(canOpen, canClose); | ||
| DeterminePosition(canOpen, canClose); | ||
| } | ||
|
|
||
| private void DetermineRole(bool canOpen, bool canClose) | ||
| { | ||
| Determine(canOpen, canClose, v => Role = v, | ||
| TokenRole.Both, TokenRole.Open, TokenRole.Close); | ||
| } | ||
|
|
||
| private void DeterminePosition(bool canOpen, bool canClose) | ||
| { | ||
| Determine(canOpen, canClose, v => Position = v, | ||
| TokenPosition.Inside, TokenPosition.Begin, TokenPosition.End); | ||
| } | ||
|
|
||
| private void Determine<T>(bool canOpen, bool canClose, Action<T> setter, T both, T open, T close) | ||
| { | ||
| if (canOpen == canClose) | ||
| { | ||
| setter(both); | ||
| } | ||
| else if (canOpen) | ||
| { | ||
| setter(open); | ||
| } | ||
| else | ||
| { | ||
| setter(close); | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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,9 @@ | ||
| namespace Markdown.Dto; | ||
|
|
||
| public enum TokenPosition | ||
| { | ||
| None = 0, | ||
| Begin, | ||
| Inside, | ||
| End, | ||
| } |
This file contains hidden or 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,9 @@ | ||
| namespace Markdown.Dto; | ||
|
|
||
| public enum TokenRole | ||
| { | ||
| None = 0, | ||
| Open, | ||
| Close, | ||
| Both, | ||
| } |
This file contains hidden or 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,12 @@ | ||
| namespace Markdown.Dto; | ||
|
|
||
| public enum TokenType | ||
| { | ||
| Text = 0, | ||
| Italic, | ||
| Strong, | ||
| Escape, | ||
| Header, | ||
| Link, | ||
| End | ||
| } | ||
This file contains hidden or 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,30 @@ | ||
| namespace Markdown.Extensions; | ||
|
|
||
| public static class StringExtensions | ||
| { | ||
| public static IEnumerable<string> EnumerateLines(this string? markdown) | ||
| { | ||
| if (markdown is null) | ||
| { | ||
| yield break; | ||
| } | ||
|
|
||
| var start = 0; | ||
|
|
||
| for (var i = 0; i < markdown.Length; i++) | ||
| { | ||
| if (markdown[i] != '\n') | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| yield return markdown[start..i]; | ||
| start = i + 1; | ||
| } | ||
|
|
||
| if (start <= markdown.Length) | ||
| { | ||
| yield return markdown[start..]; | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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,16 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net9.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="FluentAssertions" Version="8.8.0" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" /> | ||
| <PackageReference Include="NUnit" Version="4.4.0" /> | ||
| <PackageReference Include="NUnit3TestAdapter" Version="5.2.0" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or 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,6 @@ | ||
| namespace Markdown; | ||
|
|
||
| public interface IRender | ||
| { | ||
| public string RenderText(string markdown); | ||
| } |
33 changes: 33 additions & 0 deletions
33
cs/Markdown/RenderServices/Implementations/MarkdownRender.cs
This file contains hidden or 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,33 @@ | ||
| using System.Text; | ||
| using Markdown.Dto; | ||
| using Markdown.Extensions; | ||
| using Markdown.TagUtils.Abstractions; | ||
| using Markdown.TagUtils.Implementations; | ||
| using Markdown.TokensUtils; | ||
| using Markdown.TokensUtils.Abstractions; | ||
| using Markdown.TokensUtils.Implementations; | ||
|
|
||
| namespace Markdown | ||
| { | ||
| public class MarkdownRender(ITokenizer tokenizer, ITagProcessor tagProcessor) : IRender | ||
| { | ||
| public string RenderText(string markdown) | ||
| { | ||
| var markDownLines = markdown.EnumerateLines(); | ||
| var result = new StringBuilder(); | ||
| foreach (var line in markDownLines) | ||
| { | ||
| if (result.Length > 0) result.Append('\n'); | ||
| result.Append(RenderLine(line)); | ||
| } | ||
|
|
||
| return result.ToString(); | ||
| } | ||
|
|
||
| private string RenderLine(string line) | ||
| { | ||
| var tokens = tokenizer.Tokenize(line).ToList(); | ||
| return tagProcessor.Process(tokens); | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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,53 @@ | ||
| using System.Text; | ||
| using Markdown.Dto; | ||
| using Markdown.TagUtils.Abstractions; | ||
|
|
||
| public abstract class BaseTagStrategy(ITagContext context) | ||
| { | ||
| protected void ProcessTag(Token token, bool isStrong, Func<Tag, Token, bool> isInvalidCloseContext) | ||
| { | ||
| var tagsStack = context.Tags; | ||
| var parent = tagsStack.Count > 0 ? tagsStack.Peek() : null; | ||
| var canClose = isStrong ? token.Role is TokenRole.Close : token.Role is TokenRole.Close or TokenRole.Both; | ||
| var canOpen = isStrong | ||
| ? token.Role is TokenRole.Open or TokenRole.Both || | ||
| (token.Role == TokenRole.Close && tagsStack.Count > 0 && tagsStack.Peek().IsOpen) | ||
| : token.Role is TokenRole.Open or TokenRole.Both; | ||
|
|
||
| if (canClose && tagsStack.Count > 0 && !isInvalidCloseContext(parent, token)) | ||
| { | ||
| if (isStrong) | ||
| { | ||
| var popParent = tagsStack.Pop(); | ||
| var grandParent = tagsStack.Count > 0 ? tagsStack.Peek() : null; | ||
| var shouldNotClose = grandParent is not null && grandParent.Token.Type == TokenType.Italic && | ||
| grandParent.IsOpen; | ||
|
|
||
| if (shouldNotClose) | ||
| { | ||
| var newContent = popParent.Content.Append(popParent.Token.Value); | ||
| context.Append(newContent.ToString()); | ||
| } | ||
| else | ||
| { | ||
| tagsStack.Push(popParent); | ||
| context.CloseTop(); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| context.CloseTop(); | ||
| } | ||
| } | ||
| else if (canOpen) | ||
| { | ||
| context.Open(new Tag(token, new StringBuilder(token.Value), true)); | ||
| } | ||
| else | ||
| { | ||
| context.Append(token.Value); | ||
| } | ||
| } | ||
|
|
||
| public abstract void Process(Token token); | ||
| } |
This file contains hidden or 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,14 @@ | ||
| using System.Text; | ||
| using Markdown.Dto; | ||
|
|
||
| namespace Markdown.TagUtils.Abstractions; | ||
|
|
||
| public interface ITagContext : IDisposable | ||
| { | ||
| public void Append(string content); | ||
| public void CloseTop(bool isFinal = false); | ||
| public void Open(Tag tag); | ||
| public Stack<Tag> Tags { get; } | ||
| public StringBuilder Content { get; } | ||
| public bool SkipNextAsMarkup { get; set; } | ||
| } |
This file contains hidden or 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,9 @@ | ||
| using System.Text; | ||
| using Markdown.Dto; | ||
|
|
||
| namespace Markdown.TagUtils.Abstractions; | ||
|
|
||
| public interface ITagProcessor | ||
| { | ||
| public string Process(IEnumerable<Token> tokens); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as resolved.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.