From 527093d433d9200cfebb26cf72cc4a6ca8bcaa0c Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 23 Jun 2021 11:24:02 +0300 Subject: [PATCH 1/5] Docs: Add line highlight for markdown --- .../Extensions/CustomCodeBlockExtension.cs | 34 +++++ .../MarkdownPipelineBuilderExtensions.cs | 13 ++ .../Markdown/MarkDigMarkdownConverter.cs | 2 + .../Renderers/CustomCodeBlockRenderer.cs | 131 ++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs create mode 100644 modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs create mode 100644 modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs new file mode 100644 index 0000000000..95995c839b --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs @@ -0,0 +1,34 @@ +using System; +using Markdig; +using Markdig.Renderers; +using Markdig.Renderers.Html; +using Volo.Docs.Markdown.Renderers; + +namespace Volo.Docs.Markdown.Extensions +{ + public class CustomCodeBlockExtension : IMarkdownExtension + { + public void Setup(MarkdownPipelineBuilder pipeline) + { + } + + public void Setup(MarkdownPipeline pipeline, IMarkdownRenderer renderer) + { + if (renderer == null) + { + throw new ArgumentNullException(nameof(renderer)); + } + + if (renderer is TextRendererBase htmlRenderer) + { + var codeBlockRenderer = htmlRenderer.ObjectRenderers.FindExact(); + if (codeBlockRenderer != null) + { + htmlRenderer.ObjectRenderers.Remove(codeBlockRenderer); + } + + htmlRenderer.ObjectRenderers.AddIfNotAlready(new CustomCodeBlockRenderer()); + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs new file mode 100644 index 0000000000..249bf31b49 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs @@ -0,0 +1,13 @@ +using Markdig; + +namespace Volo.Docs.Markdown.Extensions +{ + public static class MarkdownPipelineBuilderExtensions + { + public static MarkdownPipelineBuilder UseCustomCodeBlock(this MarkdownPipelineBuilder pipeline) + { + pipeline.Extensions.AddIfNotAlready(); + return pipeline; + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs index 1bd858e2d0..183eeabee2 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs @@ -1,6 +1,7 @@ using System.Text; using Markdig; using Volo.Abp.DependencyInjection; +using Volo.Docs.Markdown.Extensions; namespace Volo.Docs.Markdown { @@ -15,6 +16,7 @@ namespace Volo.Docs.Markdown .UseBootstrap() .UseGridTables() .UsePipeTables() + .UseCustomCodeBlock() .Build(); } diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs new file mode 100644 index 0000000000..bddc94c439 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Markdig.Parsers; +using Markdig.Renderers; +using Markdig.Renderers.Html; +using Markdig.Syntax; + +namespace Volo.Docs.Markdown.Renderers +{ + public class CustomCodeBlockRenderer : HtmlObjectRenderer + { + private const string Pattern = @"\{([^}]+)\}"; + public bool OutputAttributesOnPre { get; set; } + + public HashSet BlocksAsDiv { get; } + + public CustomCodeBlockRenderer() + { + BlocksAsDiv = new HashSet(StringComparer.OrdinalIgnoreCase); + } + + protected override void Write(HtmlRenderer renderer, CodeBlock obj) + { + renderer.EnsureLine(); + + var fencedCodeBlock = obj as FencedCodeBlock; + if (fencedCodeBlock?.Info != null && BlocksAsDiv.Contains(fencedCodeBlock.Info)) + { + var infoPrefix = (obj.Parser as FencedCodeBlockParser)?.InfoPrefix ?? + FencedCodeBlockParser.DefaultInfoPrefix; + + if (renderer.EnableHtmlForBlock) + { + renderer.Write(" cls.StartsWith(infoPrefix, StringComparison.Ordinal) ? cls.Substring(infoPrefix.Length) : cls) + .Write('>'); + } + + renderer.WriteLeafRawLines(obj, true, true, true); + + if (renderer.EnableHtmlForBlock) + { + renderer.WriteLine(""); + } + + } + else + { + if (renderer.EnableHtmlForBlock) + { + renderer.Write("
 {"line-numbers"}});
+
+                        var lines = string.Join(",", highlightedLines);
+                        renderer.Write($"data-line={lines}>');
+                }
+
+                renderer.WriteLeafRawLines(obj, true, true);
+
+                if (renderer.EnableHtmlForBlock)
+                {
+                    renderer.WriteLine("
"); + } + } + + renderer.EnsureLine(); + } + + private List GetHighlightedLines(FencedCodeBlock fencedCodeBlock) + { + var highlightedLines = new List(); + + if (string.IsNullOrWhiteSpace(fencedCodeBlock?.Arguments)) + { + return highlightedLines; + } + + if (Regex.IsMatch(pattern: Pattern, input: fencedCodeBlock.Arguments)) + { + var match = Regex.Match(fencedCodeBlock.Arguments, Pattern); + var groups = match.Groups; + + if (groups.Count < 2 || string.IsNullOrWhiteSpace(groups[1].Value)) + { + return highlightedLines; + } + + var lines = groups[1].Value.Split(","); + foreach (var line in lines) + { + if (line.Contains("-")) + { + var numbers = line.Split("-"); + highlightedLines.AddRange(numbers.Select(number => Convert.ToInt32(number))); + } + else + { + highlightedLines.Add(Convert.ToInt32(line)); + } + } + } + + return highlightedLines; + } + } +} \ No newline at end of file From f96097eca27927ae3b75fbbc31beb9adf023d20e Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 23 Jun 2021 12:59:08 +0300 Subject: [PATCH 2/5] Refactoring for highlighted code blocks --- ...on.cs => HighlightedCodeBlockExtension.cs} | 4 +- .../MarkdownPipelineBuilderExtensions.cs | 4 +- .../Markdown/MarkDigMarkdownConverter.cs | 2 +- ...rer.cs => HighlightedCodeBlockRenderer.cs} | 78 +++++++++++-------- 4 files changed, 50 insertions(+), 38 deletions(-) rename modules/docs/src/Volo.Docs.Web/Markdown/Extensions/{CustomCodeBlockExtension.cs => HighlightedCodeBlockExtension.cs} (87%) rename modules/docs/src/Volo.Docs.Web/Markdown/Renderers/{CustomCodeBlockRenderer.cs => HighlightedCodeBlockRenderer.cs} (59%) diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/HighlightedCodeBlockExtension.cs similarity index 87% rename from modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs rename to modules/docs/src/Volo.Docs.Web/Markdown/Extensions/HighlightedCodeBlockExtension.cs index 95995c839b..d2b7858d7a 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/CustomCodeBlockExtension.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/HighlightedCodeBlockExtension.cs @@ -6,7 +6,7 @@ using Volo.Docs.Markdown.Renderers; namespace Volo.Docs.Markdown.Extensions { - public class CustomCodeBlockExtension : IMarkdownExtension + public class HighlightedCodeBlockExtension : IMarkdownExtension { public void Setup(MarkdownPipelineBuilder pipeline) { @@ -27,7 +27,7 @@ namespace Volo.Docs.Markdown.Extensions htmlRenderer.ObjectRenderers.Remove(codeBlockRenderer); } - htmlRenderer.ObjectRenderers.AddIfNotAlready(new CustomCodeBlockRenderer()); + htmlRenderer.ObjectRenderers.AddIfNotAlready(new HighlightedCodeBlockRenderer()); } } } diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs index 249bf31b49..7d9a70c80c 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Extensions/MarkdownPipelineBuilderExtensions.cs @@ -4,9 +4,9 @@ namespace Volo.Docs.Markdown.Extensions { public static class MarkdownPipelineBuilderExtensions { - public static MarkdownPipelineBuilder UseCustomCodeBlock(this MarkdownPipelineBuilder pipeline) + public static MarkdownPipelineBuilder UseHighlightedCodeBlocks(this MarkdownPipelineBuilder pipeline) { - pipeline.Extensions.AddIfNotAlready(); + pipeline.Extensions.AddIfNotAlready(); return pipeline; } } diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs index 183eeabee2..a45dc0862f 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkDigMarkdownConverter.cs @@ -16,7 +16,7 @@ namespace Volo.Docs.Markdown .UseBootstrap() .UseGridTables() .UsePipeTables() - .UseCustomCodeBlock() + .UseHighlightedCodeBlocks() .Build(); } diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs similarity index 59% rename from modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs rename to modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs index bddc94c439..6ac3b178df 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/CustomCodeBlockRenderer.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs @@ -10,14 +10,14 @@ using Markdig.Syntax; namespace Volo.Docs.Markdown.Renderers { - public class CustomCodeBlockRenderer : HtmlObjectRenderer + public class HighlightedCodeBlockRenderer : HtmlObjectRenderer { private const string Pattern = @"\{([^}]+)\}"; public bool OutputAttributesOnPre { get; set; } public HashSet BlocksAsDiv { get; } - public CustomCodeBlockRenderer() + public HighlightedCodeBlockRenderer() { BlocksAsDiv = new HashSet(StringComparer.OrdinalIgnoreCase); } @@ -46,7 +46,6 @@ namespace Volo.Docs.Markdown.Renderers { renderer.WriteLine(""); } - } else { @@ -58,19 +57,8 @@ namespace Volo.Docs.Markdown.Renderers { renderer.WriteAttributes(obj); } - - var highlightedLines = GetHighlightedLines(fencedCodeBlock); - if (highlightedLines.Any()) - { - renderer.WriteAttributes(new HtmlAttributes {Classes = new List {"line-numbers"}}); - var lines = string.Join(",", highlightedLines); - renderer.Write($"data-line={lines}> {"line-numbers"} //prevents adding line-numbers for highlighted lines + }); + var lines = string.Join(",", highlightedLines); + renderer.Write($"data-line={lines}> GetHighlightedLines(FencedCodeBlock fencedCodeBlock) { var highlightedLines = new List(); - - if (string.IsNullOrWhiteSpace(fencedCodeBlock?.Arguments)) + if (string.IsNullOrWhiteSpace(fencedCodeBlock?.Arguments) || !Regex.IsMatch(pattern: Pattern, input: fencedCodeBlock.Arguments)) { return highlightedLines; } - if (Regex.IsMatch(pattern: Pattern, input: fencedCodeBlock.Arguments)) + var match = Regex.Match(fencedCodeBlock.Arguments, Pattern); + var groups = match.Groups; + if (groups.Count < 2 || string.IsNullOrWhiteSpace(groups[1].Value)) { - var match = Regex.Match(fencedCodeBlock.Arguments, Pattern); - var groups = match.Groups; - - if (groups.Count < 2 || string.IsNullOrWhiteSpace(groups[1].Value)) - { - return highlightedLines; - } + return highlightedLines; + } - var lines = groups[1].Value.Split(","); - foreach (var line in lines) + var lines = groups[1].Value.Split(","); + foreach (var line in lines) + { + if (line.Contains("-")) { - if (line.Contains("-")) + var numbers = line.Split("-"); + + foreach (var number in numbers) { - var numbers = line.Split("-"); - highlightedLines.AddRange(numbers.Select(number => Convert.ToInt32(number))); + if (int.TryParse(number, out var lineNumber)) + { + highlightedLines.Add(lineNumber); + } } - else + } + else + { + if (int.TryParse(line, out var lineNumber)) { - highlightedLines.Add(Convert.ToInt32(line)); + highlightedLines.Add(lineNumber); } } } - + return highlightedLines; } } From 2f8ca681c880d354e734cd2f409a6524c6aa96d7 Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 23 Jun 2021 13:21:35 +0300 Subject: [PATCH 3/5] Docs: Change highlighted line background-color --- .../Renderers/HighlightedCodeBlockRenderer.cs | 17 ++++++++++++----- .../Pages/Documents/Project/Index.cshtml | 1 + .../Pages/Documents/Project/index.css | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs index 6ac3b178df..07209eb912 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs @@ -119,13 +119,20 @@ namespace Volo.Docs.Markdown.Renderers if (line.Contains("-")) { var numbers = line.Split("-"); + if (numbers.Length > 2) + { + continue; + } + + if (!int.TryParse(numbers[0], out var minLineNumber) || + !int.TryParse(numbers[1], out var maxLineNumber)) + { + continue; + } - foreach (var number in numbers) + for (var lineNumber = minLineNumber; lineNumber < maxLineNumber + 1; lineNumber++) { - if (int.TryParse(number, out var lineNumber)) - { - highlightedLines.Add(lineNumber); - } + highlightedLines.Add(lineNumber); } } else diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index b6a33ec2ad..4d59707f5e 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -27,6 +27,7 @@ + } @section scripts { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css new file mode 100644 index 0000000000..52dd43fbbe --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css @@ -0,0 +1,5 @@ +.line-highlight { + margin-top: 1.5em !important; + background: rgb(176 199 52 / 20%) !important; + padding: 1px !important; +} \ No newline at end of file From 8a4c00acf35ad02fbd0fb83d5ecc4b148b07d881 Mon Sep 17 00:00:00 2001 From: EngincanV Date: Wed, 23 Jun 2021 15:15:29 +0300 Subject: [PATCH 4/5] Docs: Change List to HashSet for highlighted lines --- .../Markdown/Renderers/HighlightedCodeBlockRenderer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs index 07209eb912..9a0f6afcf2 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/Renderers/HighlightedCodeBlockRenderer.cs @@ -98,9 +98,9 @@ namespace Volo.Docs.Markdown.Renderers } } - private List GetHighlightedLines(FencedCodeBlock fencedCodeBlock) + private HashSet GetHighlightedLines(FencedCodeBlock fencedCodeBlock) { - var highlightedLines = new List(); + var highlightedLines = new HashSet(); if (string.IsNullOrWhiteSpace(fencedCodeBlock?.Arguments) || !Regex.IsMatch(pattern: Pattern, input: fencedCodeBlock.Arguments)) { return highlightedLines; From e936293d6ea7c12fbd52783222db605b8fa3c8d7 Mon Sep 17 00:00:00 2001 From: Alper Ebicoglu Date: Wed, 23 Jun 2021 15:44:42 +0300 Subject: [PATCH 5/5] change highlight color --- .../src/Volo.Docs.Web/Pages/Documents/Project/index.css | 9 ++++----- .../Volo.Docs.Web/Pages/Documents/Project/index.min.css | 1 + .../src/Volo.Docs.Web/Pages/Documents/Project/index.scss | 7 +++++++ modules/docs/src/Volo.Docs.Web/compilerconfig.json | 4 ++++ 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.min.css create mode 100644 modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css index 52dd43fbbe..cd3e581996 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.css @@ -1,5 +1,4 @@ -.line-highlight { - margin-top: 1.5em !important; - background: rgb(176 199 52 / 20%) !important; - padding: 1px !important; -} \ No newline at end of file +.code-toolbar .line-highlight { + margin-top: 1.5em !important; + background: rgba(233, 237, 241, 0.34) !important; + padding: 1px !important; } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.min.css b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.min.css new file mode 100644 index 0000000000..20ff809dd8 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.min.css @@ -0,0 +1 @@ +.code-toolbar .line-highlight{margin-top:1.5em !important;background:rgba(233,237,241,.34) !important;padding:1px !important;} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss new file mode 100644 index 0000000000..2b2a8bb520 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.scss @@ -0,0 +1,7 @@ +.code-toolbar { + .line-highlight { + margin-top: 1.5em !important; + background: rgba(233, 237, 241, 0.34) !important; + padding: 1px !important; + } +} diff --git a/modules/docs/src/Volo.Docs.Web/compilerconfig.json b/modules/docs/src/Volo.Docs.Web/compilerconfig.json index 3645b5a8f5..9b210b9e49 100644 --- a/modules/docs/src/Volo.Docs.Web/compilerconfig.json +++ b/modules/docs/src/Volo.Docs.Web/compilerconfig.json @@ -6,5 +6,9 @@ { "outputFile": "Pages/Documents/Project/index.css", "inputFile": "Pages/Documents/Project/index.less" + }, + { + "outputFile": "Pages/Documents/Project/index.css", + "inputFile": "Pages/Documents/Project/index.scss" } ] \ No newline at end of file