Merge pull request #9409 from abpframework/EngincanV/docs-line-highlight

Docs: Highlight Code Lines
pull/9423/head
ebicoglu 4 years ago committed by GitHub
commit 9dce13103e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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 HighlightedCodeBlockExtension : 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> htmlRenderer)
{
var codeBlockRenderer = htmlRenderer.ObjectRenderers.FindExact<CodeBlockRenderer>();
if (codeBlockRenderer != null)
{
htmlRenderer.ObjectRenderers.Remove(codeBlockRenderer);
}
htmlRenderer.ObjectRenderers.AddIfNotAlready(new HighlightedCodeBlockRenderer());
}
}
}
}

@ -0,0 +1,13 @@
using Markdig;
namespace Volo.Docs.Markdown.Extensions
{
public static class MarkdownPipelineBuilderExtensions
{
public static MarkdownPipelineBuilder UseHighlightedCodeBlocks(this MarkdownPipelineBuilder pipeline)
{
pipeline.Extensions.AddIfNotAlready<HighlightedCodeBlockExtension>();
return pipeline;
}
}
}

@ -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()
.UseHighlightedCodeBlocks()
.Build();
}

@ -0,0 +1,150 @@
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 HighlightedCodeBlockRenderer : HtmlObjectRenderer<CodeBlock>
{
private const string Pattern = @"\{([^}]+)\}";
public bool OutputAttributesOnPre { get; set; }
public HashSet<string> BlocksAsDiv { get; }
public HighlightedCodeBlockRenderer()
{
BlocksAsDiv = new HashSet<string>(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("<div")
.WriteAttributes(obj.TryGetAttributes(),
cls => cls.StartsWith(infoPrefix, StringComparison.Ordinal) ? cls.Substring(infoPrefix.Length) : cls)
.Write('>');
}
renderer.WriteLeafRawLines(obj, true, true, true);
if (renderer.EnableHtmlForBlock)
{
renderer.WriteLine("</div>");
}
}
else
{
if (renderer.EnableHtmlForBlock)
{
renderer.Write("<pre ");
if (OutputAttributesOnPre)
{
renderer.WriteAttributes(obj);
}
WriteHighlightedCodeLines(renderer, fencedCodeBlock);
if (!OutputAttributesOnPre)
{
renderer.WriteAttributes(obj);
}
renderer.Write('>');
}
renderer.WriteLeafRawLines(obj, true, true);
if (renderer.EnableHtmlForBlock)
{
renderer.WriteLine("</code></pre>");
}
}
renderer.EnsureLine();
}
private void WriteHighlightedCodeLines(HtmlRenderer renderer, FencedCodeBlock fencedCodeBlock)
{
var highlightedLines = GetHighlightedLines(fencedCodeBlock);
if (highlightedLines.Any())
{
renderer.WriteAttributes(new HtmlAttributes
{
Classes = new List<string> {"line-numbers"} //prevents adding line-numbers for highlighted lines
});
var lines = string.Join(",", highlightedLines);
renderer.Write($"data-line={lines}><code");
}
else
{
renderer.Write("><code");
}
}
private HashSet<int> GetHighlightedLines(FencedCodeBlock fencedCodeBlock)
{
var highlightedLines = new HashSet<int>();
if (string.IsNullOrWhiteSpace(fencedCodeBlock?.Arguments) || !Regex.IsMatch(pattern: Pattern, input: fencedCodeBlock.Arguments))
{
return highlightedLines;
}
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("-");
if (numbers.Length > 2)
{
continue;
}
if (!int.TryParse(numbers[0], out var minLineNumber) ||
!int.TryParse(numbers[1], out var maxLineNumber))
{
continue;
}
for (var lineNumber = minLineNumber; lineNumber < maxLineNumber + 1; lineNumber++)
{
highlightedLines.Add(lineNumber);
}
}
else
{
if (int.TryParse(line, out var lineNumber))
{
highlightedLines.Add(lineNumber);
}
}
}
return highlightedLines;
}
}
}

@ -27,6 +27,7 @@
<abp-script type="@typeof(MalihuCustomScrollbarPluginStyleBundleContributor)" />
<abp-style src="/Pages/Documents/Project/bootstrap-toc.css" />
<abp-style src="/Pages/Documents/Shared/Styles/vs.css" />
<abp-style src="/Pages/Documents/Project/index.css"/>
</abp-style-bundle>
}
@section scripts {

@ -0,0 +1,4 @@
.code-toolbar .line-highlight {
margin-top: 1.5em !important;
background: rgba(233, 237, 241, 0.34) !important;
padding: 1px !important; }

@ -0,0 +1 @@
.code-toolbar .line-highlight{margin-top:1.5em !important;background:rgba(233,237,241,.34) !important;padding:1px !important;}

@ -0,0 +1,7 @@
.code-toolbar {
.line-highlight {
margin-top: 1.5em !important;
background: rgba(233, 237, 241, 0.34) !important;
padding: 1px !important;
}
}

@ -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"
}
]
Loading…
Cancel
Save