From 5b29fb3cb225fe0f140ba81faefd95baba861994 Mon Sep 17 00:00:00 2001 From: Gorniaky Date: Fri, 4 Sep 2026 19:15:24 -0300 Subject: [PATCH] refactor: implement MarkdownToHtmlConverter for improved markdown processing --- scripts/docs/generate.dart | 95 +--------------- scripts/docs/markdown_to_html_converter.dart | 107 +++++++++++++++++++ 2 files changed, 111 insertions(+), 91 deletions(-) create mode 100644 scripts/docs/markdown_to_html_converter.dart diff --git a/scripts/docs/generate.dart b/scripts/docs/generate.dart index aa3f089..2b484d5 100644 --- a/scripts/docs/generate.dart +++ b/scripts/docs/generate.dart @@ -6,14 +6,13 @@ import "dart:typed_data"; import "package:args/command_runner.dart"; import "package:discloud/cli/runner.dart"; import "package:discloud/version.dart"; -import "package:markdown/markdown.dart"; import "package:path/path.dart"; import "generate/commands.dart"; import "generate/index.dart"; +import "markdown_to_html_converter.dart"; const _docsRootPath = "docs"; -const _mdDocsExt = ".md"; void main() async { final docRootDir = Directory(_docsRootPath); @@ -46,95 +45,9 @@ void main() async { commands(header: header, runner: runner), ]); - final entities = await docRootDir - .list(recursive: true) - .where((e) => e is File && extension(e.path) == _mdDocsExt) - .toList(); - - final entitiesPaths = entities.map((e) => e.path).toSet(); - - for (final mdFile in entities.whereType()) { - final mdContent = await mdFile.readAsString(); - - final htmlContent = markdownToHtml( - mdContent, - blockSyntaxes: const [ - AlertBlockSyntax(), - BlockquoteSyntax(), - CodeBlockSyntax(), - DummyBlockSyntax(), - EmptyBlockSyntax(), - FencedBlockquoteSyntax(), - FencedCodeBlockSyntax(), - FootnoteDefSyntax(), - HeaderSyntax(), - HeaderWithIdSyntax(), - HorizontalRuleSyntax(), - HtmlBlockSyntax(), - LinkReferenceDefinitionSyntax(), - OrderedListSyntax(), - OrderedListWithCheckboxSyntax(), - ParagraphSyntax(), - SetextHeaderSyntax(), - SetextHeaderWithIdSyntax(), - TableSyntax(), - UnorderedListSyntax(), - UnorderedListWithCheckboxSyntax(), - ], - inlineSyntaxes: [ - _LocalLinkMdSyntax(localFiles: entitiesPaths), - AutolinkExtensionSyntax(), - AutolinkSyntax(), - CodeSyntax(), - ColorSwatchSyntax(), - DecodeHtmlSyntax(), - EmailAutolinkSyntax(), - EmojiSyntax(), - EmphasisSyntax.asterisk(), - EmphasisSyntax.underscore(), - EscapeHtmlSyntax(), - EscapeSyntax(), - ImageSyntax(), - InlineHtmlSyntax(), - LineBreakSyntax(), - LinkSyntax(), - SoftLineBreakSyntax(), - StrikethroughSyntax(), - ], - ); - - final htmlFilename = "${basenameWithoutExtension(mdFile.path)}.html"; - - final File htmlFile = .new(joinAll([dirname(mdFile.path), htmlFilename])); - - await htmlFile.writeAsString(htmlContent); - } -} - -class _LocalLinkMdSyntax extends InlineSyntax { - static const _pattern = r"\[([^\]]+)\]\(([^)]+\.md)\)"; - - new({required this.localFiles}) : super(_pattern); - - final Set localFiles; - - @override - bool onMatch(InlineParser parser, Match match) { - final title = match.group(1)!; - final Element element = .text("a", title); - parser.addNode(element); - - final mdFilePath = match.group(2)!; - final path = joinAll([_docsRootPath, mdFilePath]); - - if (localFiles.contains(path)) { - final htmlFilename = "${basenameWithoutExtension(mdFilePath)}.html"; - final htmlFilePath = joinAll([dirname(mdFilePath), htmlFilename]); - element.attributes["href"] = htmlFilePath; - return true; - } + final converter = MarkdownToHtmlConverter(directory: docRootDir); - element.attributes["href"] = mdFilePath; - return true; + await for (final (file, content) in converter.convert()) { + await file.writeAsString(content); } } diff --git a/scripts/docs/markdown_to_html_converter.dart b/scripts/docs/markdown_to_html_converter.dart new file mode 100644 index 0000000..bec25d3 --- /dev/null +++ b/scripts/docs/markdown_to_html_converter.dart @@ -0,0 +1,107 @@ +import "dart:io"; + +import "package:markdown/markdown.dart"; +import "package:path/path.dart"; + +const _mdExt = ".md"; + +final class MarkdownToHtmlConverter { + const new({required this.directory}); + + final Directory directory; + + Stream<(File file, String content)> convert() async* { + final entities = await directory + .list(recursive: true) + .where((e) => e is File && extension(e.path) == _mdExt) + .toList(); + + final entitiesPaths = entities.map((e) => e.path).toSet(); + + for (final mdFile in entities.whereType()) { + final mdContent = await mdFile.readAsString(); + + final htmlContent = markdownToHtml( + mdContent, + blockSyntaxes: const [ + AlertBlockSyntax(), + BlockquoteSyntax(), + CodeBlockSyntax(), + DummyBlockSyntax(), + EmptyBlockSyntax(), + FencedBlockquoteSyntax(), + FencedCodeBlockSyntax(), + FootnoteDefSyntax(), + HeaderSyntax(), + HeaderWithIdSyntax(), + HorizontalRuleSyntax(), + HtmlBlockSyntax(), + LinkReferenceDefinitionSyntax(), + OrderedListSyntax(), + OrderedListWithCheckboxSyntax(), + ParagraphSyntax(), + SetextHeaderSyntax(), + SetextHeaderWithIdSyntax(), + TableSyntax(), + UnorderedListSyntax(), + UnorderedListWithCheckboxSyntax(), + ], + inlineSyntaxes: [ + _LocalLinkMdSyntax(directory: directory, localFiles: entitiesPaths), + AutolinkExtensionSyntax(), + AutolinkSyntax(), + CodeSyntax(), + ColorSwatchSyntax(), + DecodeHtmlSyntax(), + EmailAutolinkSyntax(), + EmojiSyntax(), + EmphasisSyntax.asterisk(), + EmphasisSyntax.underscore(), + EscapeHtmlSyntax(), + EscapeSyntax(), + ImageSyntax(), + InlineHtmlSyntax(), + LineBreakSyntax(), + LinkSyntax(), + SoftLineBreakSyntax(), + StrikethroughSyntax(), + ], + ); + + final htmlFilename = "${basenameWithoutExtension(mdFile.path)}.html"; + + final File htmlFile = .new(joinAll([dirname(mdFile.path), htmlFilename])); + + yield (htmlFile, htmlContent); + } + } +} + +class _LocalLinkMdSyntax extends InlineSyntax { + static const _pattern = r"\[([^\]]+)\]\(([^)]+\.md)\)"; + + new({required this.directory, required this.localFiles}) : super(_pattern); + + final Directory directory; + final Set localFiles; + + @override + bool onMatch(InlineParser parser, Match match) { + final title = match.group(1)!; + final Element element = .text("a", title); + parser.addNode(element); + + final mdFilePath = match.group(2)!; + final path = joinAll([directory.path, mdFilePath]); + + if (localFiles.contains(path)) { + final htmlFilename = "${basenameWithoutExtension(mdFilePath)}.html"; + final htmlFilePath = joinAll([dirname(mdFilePath), htmlFilename]); + element.attributes["href"] = htmlFilePath; + return true; + } + + element.attributes["href"] = mdFilePath; + return true; + } +}