完美:C# Blazor中顯示Markdown並添加程式碼高亮

完美:C# Blazor中顯示Markdown並添加程式碼高亮

自認為應該是比較完美了,下面說說怎麼做的。

最後更新 2022/2/27 下午5:46
沙漠尽头的狼
預計閱讀 4 分鐘
分類
Blazor
標籤
.NET C# Blazor Markdown

昨天發了一篇介紹這個庫:C# Blazor 中顯示 Markdown 檔案,介紹怎麼在 Blazor 中顯示 Markdown 內容的文章,文章內的程式碼沒有高亮,思來想去,還是要做好,於是上網搜尋到這篇文章.NET C# Blazor 服務端渲染 Markdown,現在渲染效果如下:

自認為應該是比較完美了,下面說說怎麼做的。

一、準備工具

1.1 新增 Markdown 轉 html 套件:Markdig

Markdig:Markdig 是一個快速、強大、符合CommonMark標準、可擴充的 .NET Markdown 處理器。

<PackageReference Include="Markdig" Version="0.27.0" />

1.2 引入 Prism 外掛

Prism非彼Prism,是一個 JS 外掛:Prism 是一個輕量級、健壯且優雅的語法高亮庫。這是Dabblet的一個衍生專案。

_Layout.cshtmlhead中引入:

<head>
  ....
  <!--重設瀏覽器樣式-->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.css"
  />
  <!--程式碼區塊主題-->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/themes/prism-coy.min.css"
  />
  <!--工具列外掛-->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/toolbar/prism-toolbar.min.css"
  />
  <!--行號外掛-->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/line-numbers/prism-line-numbers.min.css"
  />
  ...
</head>
<body>
  ...
  <!--prism核心js (用於渲染程式碼區塊)-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/prism.min.js"></script>
  <!--顯示程式碼區塊行號-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
  <!--工具列(一些外掛的前置依賴)-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/toolbar/prism-toolbar.min.js"></script>
  <!--程式碼區塊顯示語言名稱-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/show-language/prism-show-language.min.js"></script>
  <!--複製程式碼-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
  <!--自動去cdn載入對應語言的程式碼高亮js-->
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.27.0/plugins/autoloader/prism-autoloader.min.js"></script>
</body>

二、使用

我將Markdown展示單獨提取成元件MarkdownComponent.razor,將載入的Markdown檔案相對路徑、需要連結的文章連結和原始碼連結做成參數,方便後面其他工具複用,下面的程式碼片段主要在這個檔案內。

元件參數定義:

@code {
    [Parameter]
    public string LocalPostFilePath { get; set; } = null!;

    [Parameter]
    public string RemotePostUrl { get; set; } = null!;

    [Parameter]
    public string SourceCodeUrl { get; set; } = null!;
}

Markdown內容讀取,Markdown格式轉htmlOnInitializedAsync()方法中定義:

protected override async Task OnInitializedAsync()
{
    var markdownData = await File.ReadAllTextAsync(LocalPostFilePath);

    // markdown 轉為 html
    var htmlData = Markdown.ToHtml(markdownData);

    // 轉為 prism 支援的語言標記(非必須,可以刪除)
    htmlData = htmlData.Replace("language-golang", "language-go");

    // TODO: 使用 https://github.com/mganss/HtmlSanitizer 清洗html中的xss
    if (htmlData.Contains("<script") || htmlData.Contains("<link"))
    {
        _hasXss = true;
    }

    // 將 普通文字 轉為 可以渲染的html的類型
    _postHtmlContent = (MarkupString) htmlData;
}

最後一步,需要在元件完成後,呼叫Prism外掛方法,寫在方法OnAfterRenderAsync(bool firstRender)中,這是做程式碼高亮的關鍵程式碼:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    await _jsRuntime.InvokeVoidAsync("Prism.highlightAll");
}

渲染相對來說就簡單了(只針對我們使用),見下面的程式碼:

<div class="line-numbers">
  @{ if (_hasXss) { @_postHtmlContent.ToString() } else { @_postHtmlContent } }
</div>

IcoTool.razor呼叫該元件:

<MarkdownComponent
  LocalPostFilePath="wwwroot/2022/02/2022-02-22_02.md"
  RemotePostUrl="https://dotnet9.com/2022/02/Perfect-Display-Markdown-in-Csharp-Blazor-and-add-code-highlighting"
  SourceCodeUrl="https://github.com/dotnet9/dotnet9.com/blob/develop/src/Dotnet9.Tools.Web/Pages/Public/ImageTools/IcoTool.razor"
/>

當然元件封裝看個人需求,大致思路是上面的,就不貼詳細程式碼了,有興趣看看Dotnet9 工具箱原始碼

參考文章:

繼續探索

延伸閱讀

更多文章
同分類 / 同標籤 2024/2/29

Winform中也可以這樣做資料展示

在做winform開發的過程中,經常需要做資料展示的功能,之前一直使用的是gridcontrol控制項,今天想透過一個範例,跟大家介紹一下如何在winform blazor hybrid中使用ant design blazor中的table元件做資料展示。

繼續閱讀
同分類 / 同標籤 2024/2/29

Winform的介面也可以變好看?

前幾天跟大家介紹了在winform中使用blazor hybrid,而且還說配上blazor的UI可以讓我們的winform程式設計的更加好看,接下來我想以一個在winform blazor hybrid中繪圖的範例來進行說明,希望對你有所幫助。

繼續閱讀