-
Notifications
You must be signed in to change notification settings - Fork 317
Савицких Антон #270
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
base: master
Are you sure you want to change the base?
Савицких Антон #270
Changes from 1 commit
fb3a3fc
3d2aa9f
89b0a04
fb8d33b
5f2ce89
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,129 @@ | ||
| using System.Text; | ||
| using Markdown.Enums; | ||
| using Markdown.Models; | ||
| using Markdown.Models.SyntaxTreeModels; | ||
|
|
||
| namespace Markdown.Entities.Builders | ||
| { | ||
| /// <summary> | ||
| /// Преобразует абстрактное синтаксическое дерево (AST) в HTML-код. | ||
| /// Выполняет обход дерева в глубину и генерирует соответствующие HTML-теги для каждого узла. | ||
| /// </summary> | ||
| /// <param name="tree">Абстрактное синтаксическое дерево для преобразования</param> | ||
| /// <returns>HTML-код, соответствующий структуре исходного дерева</returns> | ||
| /// <remarks> | ||
| /// Для каждого типа узла AST генерирует соответствующий HTML-тег: | ||
| /// - Заголовки → h1 | ||
| /// - Жирный текст → strong | ||
| /// - Курсив → em | ||
| /// - Параграфы → p | ||
| /// </remarks> | ||
| public class HtmlBuilder : IBuilder | ||
| { | ||
| private readonly StringBuilder _htmlBuilder; | ||
| private readonly Dictionary<NodeType, string> _tagMapping; | ||
|
|
||
| public HtmlBuilder() | ||
| { | ||
| _htmlBuilder = new StringBuilder(); | ||
| _tagMapping = new Dictionary<NodeType, string> | ||
| { | ||
| { NodeType.Document, "" }, | ||
| { NodeType.Paragraph, "p" }, | ||
| { NodeType.Header, "h1" }, | ||
| { NodeType.Bold, "strong" }, | ||
| { NodeType.Italic, "em" }, | ||
| { NodeType.Text, "" } | ||
| }; | ||
| } | ||
|
|
||
| public string Build(ISyntaxTree tree) | ||
| { | ||
| if (tree == null) | ||
| return string.Empty; | ||
|
|
||
| _htmlBuilder.Clear(); | ||
| BuildNodes(tree.Tree); | ||
| return _htmlBuilder.ToString(); | ||
| } | ||
|
|
||
| private void BuildNodes(List<Node> nodes) | ||
| { | ||
| foreach (var node in nodes) | ||
| { | ||
| BuildNode(node); | ||
| } | ||
| } | ||
|
|
||
| private void BuildNode(Node node) | ||
| { | ||
| switch (node.Type) | ||
| { | ||
| case NodeType.Text: | ||
| BuildTextNode(node); | ||
| break; | ||
| case NodeType.Document: | ||
| BuildDocumentNode(node); | ||
| break; | ||
| default: | ||
| BuildFormattedNode(node); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| private void BuildTextNode(Node node) | ||
| { | ||
| if (!string.IsNullOrEmpty(node.Value)) | ||
| { | ||
| var escapedText = EscapeHtml(node.Value); | ||
| _htmlBuilder.Append(escapedText); | ||
| } | ||
| } | ||
|
|
||
| private void BuildDocumentNode(Node node) | ||
| { | ||
| if (node.ChildrenNodes != null) | ||
| { | ||
| BuildNodes(node.ChildrenNodes); | ||
| } | ||
| } | ||
|
|
||
| private void BuildFormattedNode(Node node) | ||
| { | ||
| var tagName = _tagMapping[node.Type]; | ||
|
|
||
| if (!string.IsNullOrEmpty(tagName)) | ||
| { | ||
| _htmlBuilder.Append($"<{tagName}>"); | ||
| } | ||
|
|
||
| if (node.ChildrenNodes != null && node.ChildrenNodes.Count > 0) | ||
| { | ||
| BuildNodes(node.ChildrenNodes); | ||
| } | ||
| else if (!string.IsNullOrEmpty(node.Value)) | ||
| { | ||
| BuildTextNode(node); | ||
| } | ||
|
|
||
| if (!string.IsNullOrEmpty(tagName)) | ||
| { | ||
| _htmlBuilder.Append($"</{tagName}>"); | ||
| } | ||
| } | ||
|
|
||
| private string EscapeHtml(string text) | ||
| { | ||
| if (string.IsNullOrEmpty(text)) | ||
| return text; | ||
|
|
||
| // Эскейпинг HTML-символов для безопасности | ||
| return text | ||
| .Replace("&", "&") | ||
| .Replace("<", "<") | ||
| .Replace(">", ">") | ||
| .Replace("\"", """) | ||
| .Replace("'", "'"); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
| using Markdown.Models.SyntaxTree; | ||
| using Markdown.Models.SyntaxTreeModels; | ||
|
|
||
| namespace Markdown.Entities.Builders | ||
| { | ||
| /// <summary> | ||
| /// Преобразует абстрактное синтаксическое дерево (AST) в текст с новой разметкой. | ||
| /// </summary> | ||
| /// <param name="tree">Абстрактное синтаксическое дерево для преобразования</param> | ||
| /// <returns>Текст с измененной разметкой</returns> | ||
| public interface IBuilder | ||
| { | ||
| string Build(ISyntaxTree tree); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| using Markdown.Entities.Builders; | ||
| using Markdown.Entities.Parsers; | ||
| using Markdown.Entities.Renderers; | ||
| using Markdown.Models.SyntaxTree; | ||
|
|
||
| namespace Markdown.Entities.Converters | ||
| { | ||
| /// <summary> | ||
| /// Выполняет полный цикл преобразования одного языка разметки в другой. | ||
| /// Координирует работу токенизатора и билдера. | ||
| /// Конструктор позволяет определить желаемый билдер и токенизатор под текущую задачу, например | ||
| /// в нашем случае токенизатор умеющий работать с markdown-разметкой а buidler который умеет строить | ||
| /// по синтаксическому дереву исходный текст с html-разметкой | ||
| /// </summary> | ||
| /// <param name="text">Исходный Markdown-текст</param> | ||
| /// <returns>Строка с HTML-разметкой</returns> | ||
| /// <remarks> | ||
| /// Последовательность преобразований: | ||
| /// 1. Токенизация исходного текста | ||
| /// 2. Построение абстрактного синтаксического дерева (AST) | ||
| /// 3. Рендеринг AST в HTML-формат | ||
| /// </remarks> | ||
| public class Converter : IConverter | ||
| { | ||
| public IBuilder Builder { get; } | ||
| public ITokenizer Tokenizer { get; } | ||
|
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. Можно сделать приватными readonly полями, думаю конвертер не подразумевает отдельное их использование в обход своей логики 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. ok |
||
|
|
||
| public Converter(IBuilder builder, ITokenizer tokenizer) | ||
| { | ||
| Builder = builder; | ||
| Tokenizer = tokenizer; | ||
| } | ||
|
|
||
| public string Convert(string text) | ||
| { | ||
| if (Builder != null && Tokenizer != null) | ||
| { | ||
| var tokens = Tokenizer.Tokenize(text); | ||
| var ast = new SyntaxTree(tokens); | ||
| var convertedText = Builder.Build(ast); | ||
| return convertedText; | ||
| } | ||
| throw new NullReferenceException(); | ||
|
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. ok |
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| | ||
| namespace Markdown.Entities.Renderers | ||
| { | ||
| /// <summary> | ||
| /// Интерфейс для класса-конвертера который умеет конвертировать один язык разметки в другой, например конвертер из Markdown в HTML | ||
| /// <param name="text">Исходный текст с определенным языком разметки который хотим преобразовать</param> | ||
| /// </summary> | ||
| public interface IConverter | ||
| { | ||
| string Convert(string text); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| using Markdown.Models; | ||
|
|
||
| namespace Markdown.Entities.Parsers | ||
| { | ||
| /// <summary> | ||
| /// Интерфейс для класса который будет заниматься преобразованием исходного текста в список токенов для дальнейшего построения синтаксического дерева. | ||
| /// Умеет преобразовывать как целый текст в набор токенов, так и обрабатывать коллекции отдельных строк превращая их в список токенов | ||
| /// </summary> | ||
| public interface ITokenizer | ||
| { | ||
| List<Token> Tokenize(string text); | ||
|
|
||
| List<string> TextToLines(string text); | ||
|
|
||
| List<Token> TokenizeLines(IEnumerable<string> lines); | ||
|
|
||
| List<Token> TokenizeLine(string line); | ||
|
Comment on lines
+13
to
+17
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. ++ |
||
| } | ||
| } | ||
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.
Может вынести куда-нибудь в отдельный файл или в поля класса, всё равно он не изменяется
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.
ok