diff --git a/src/Nfdi4Plants.Fornax/Loaders.fs b/src/Nfdi4Plants.Fornax/Loaders.fs index 29fb405..ad88757 100644 --- a/src/Nfdi4Plants.Fornax/Loaders.fs +++ b/src/Nfdi4Plants.Fornax/Loaders.fs @@ -2,6 +2,7 @@ namespace Fornax.Nfdi4Plants module Pipelines = open Markdig + open Fornax.Nfdi4Plants.MarkdigExtensions.NfdiCode open Fornax.Nfdi4Plants.MarkdigExtensions.NfdiHeader open Fornax.Nfdi4Plants.MarkdigExtensions.NfdiSidebarElementHeader @@ -10,6 +11,7 @@ module Pipelines = .UseAdvancedExtensions() .UseEmojiAndSmiley() .UseNFDIHeader() + .UseNFDICodeBlock() .Build() let sidebarMarkdownPipeline = diff --git a/src/Nfdi4Plants.Fornax/MarkdigExtensions/nfdi-code.fs b/src/Nfdi4Plants.Fornax/MarkdigExtensions/nfdi-code.fs new file mode 100644 index 0000000..8a02102 --- /dev/null +++ b/src/Nfdi4Plants.Fornax/MarkdigExtensions/nfdi-code.fs @@ -0,0 +1,86 @@ +namespace Fornax.Nfdi4Plants.MarkdigExtensions + +open System.Text +open Markdig.Parsers; +open Markdig.Renderers; +open Markdig.Renderers.Html; +open Markdig.Syntax; +open Markdig + +module NfdiCode = + + open System + + // https://github.com/ilich/Markdig.Prism/blob/main/src/Markdig.Prism/PrismCodeBlockRenderer.cs + type NFDICodeBlockRenderer() = + inherit HtmlObjectRenderer() + + let extractSourcecode (node: LeafBlock) = + let code = new StringBuilder() + let lines = node.Lines.Lines + let totalLines = lines.Length + let rec appendLines (counter: int) (c: StringBuilder) = + if counter >= totalLines then + c + else + let line = lines[counter] + let slice = line.Slice + if isNull slice.Text then + appendLines (counter + 1) c + else + let lineText = slice.Text.Substring(slice.Start, slice.Length); + if counter > 0 then + appendLines (counter+1) (c.AppendLine().Append(lineText)) + else + appendLines (counter+1) (c.Append(lineText)) + appendLines 0 code + |> fun x -> x.ToString() + + override this.Write(renderer : HtmlRenderer , cb : CodeBlock ) = + + if cb :? FencedCodeBlock && cb.Parser :? FencedCodeBlockParser then + let fcb = cb :?> FencedCodeBlock + let parser = cb.Parser :?> FencedCodeBlockParser + let languageCode = fcb.Info.Replace(parser.InfoPrefix, "").Trim() + let code = extractSourcecode(cb) + if languageCode = "" then + renderer + .Write("") + .Write(code) + .Write("") + |> ignore + else + let attributes = new HtmlAttributes() + attributes.AddClass($"language-{languageCode}") + + renderer + .Write("") + .Write(code) + .Write("") + |> ignore + else + // let codeBlockRenderer = new CodeBlockRenderer() + renderer.Write(cb) |> ignore + + /// An extension for Markdig that highlights syntax in fenced code blocks + type NFDICodeExtension() = + + interface IMarkdownExtension with + + member __.Setup(_) = () + + member __.Setup(_, renderer) = + renderer.ObjectRenderers.ReplaceOrAdd(new NFDICodeBlockRenderer()) |> ignore + + open System.Runtime.CompilerServices + + [] + type MarkdownPipelineBuilderExtensions() = + [] + // Highlight code in fenced code blocks + // The Markdig to add the extension to + static member UseNFDICodeBlock(pipeline : MarkdownPipelineBuilder) = + pipeline.Extensions.Add(NFDICodeExtension()) + pipeline \ No newline at end of file diff --git a/src/Nfdi4Plants.Fornax/Nfdi4Plants.Fornax.fsproj b/src/Nfdi4Plants.Fornax/Nfdi4Plants.Fornax.fsproj index f9243d7..2e9b97b 100644 --- a/src/Nfdi4Plants.Fornax/Nfdi4Plants.Fornax.fsproj +++ b/src/Nfdi4Plants.Fornax/Nfdi4Plants.Fornax.fsproj @@ -18,6 +18,7 @@ true +