C#實現生成Markdown文檔目錄樹

1前言

(昨天那篇排版有點問題,不能忍,今天重發!)

之前我寫了一篇關于C#處理Markdown文檔的文章:C#解析Markdown文檔,實現替換圖片鏈接操作

算是第一次嘗試使用C#處理Markdown文檔,然后最近又把博客網站的前臺改了一下,目前文章渲染使用Editor.md組件在前端渲染,但這個插件生成的目錄樹很丑,我魔改了一下換成bootstrap5-treeview組件,好看多了。詳見這篇文章:魔改editormd組件,優化ToC渲染效果

此前我一直想用后端來渲染markdown文章而不得,經過這個操作,思路就打開了,也就有了本文的C#實現。

2準備工作

依然是使用Markdig庫

這個庫雖然基本沒有文檔,使用全靠猜,但目前沒有好的選擇,只能暫時選這個,我甚至一度萌生了想要重新造輪子的想法,不過由于之前沒做過類似的工作加上最近空閑時間嚴重不足,所以暫時把這個想法打消了。

(或許以后有空真得來重新造個輪子,這Markdig庫沒文檔用得太惡心了)

markdown

文章結構是這樣的,篇幅關系只把標題展示出來

##?DjangoAdmin
###?一些參考資料
##?界面主題
###?SimpleUI
####?一些相關的參考資料
###?django-jazzmin
##?定制案例
###?添加自定義列
####?效果圖
####?實現過程
####?擴展:添加鏈接
###?顯示進度條
####?效果圖
####?實現過程
###?頁面上顯示合計數額
####?效果圖
####?實現過程
#####?admin.py
#####?template
####?參考資料
###?分權限的軟刪除
####?實現過程
#####?models.py
#####?admin.py
##?擴展工具
###?Django?AdminPlus
###?django-adminactions

Markdig庫

先讀取

var?md?=?File.ReadAllText(filepath);
var?document?=?Markdown.Parse(md);

得到document對象之后,就可以對里面的元素進行遍歷,Markdig把markdown文檔處理成一個一個的block,通過這樣遍歷就可以處理每一個block

foreach?(var?block?in?document.AsEnumerable())?{//?...
}

不同的block類型在 Markdig.Syntax 命名空間下,通過 Assemblies 瀏覽器可以看到,根據字面意思,我找到了 HeadingBlock ,試了一下,確實就是代表標題的 block。

那么判斷一下,把無關的block去掉

foreach?(var?block?in?document.AsEnumerable())?{if?(block?is?not?HeadingBlock?heading)?continue;//?...
}

這一步就搞定了

定義結構

需要倆class

第一個是代表一個標題元素,父子關系的標題使用 idpid 關聯

class?Heading?{public?int?Id?{?get;?set;?}public?int?Pid?{?get;?set;?}?=?-1;public?string??Text?{?get;?set;?}public?int?Level?{?get;?set;?}
}

第二個是代表一個樹節點,類似鏈表結構

public?class?TocNode?{public?string??Text?{?get;?set;?}public?string??Href?{?get;?set;?}public?List<string>??Tags?{?get;?set;?}public?List<TocNode>??Nodes?{?get;?set;?}
}

準備工作搞定,開始寫核心代碼

3關鍵代碼

邏輯跟我前面那篇用JS實現的文章是一樣的

遍歷標題block,添加到一個列表中

foreach?(var?block?in?document.AsEnumerable())?{if?(block?is?not?HeadingBlock?heading)?continue;var?item?=?new?Heading?{Level?=?heading.Level,?Text?=?heading.Inline?.FirstChild?.ToString()};headings.Add(item);Console.WriteLine($"{new?string('#',?item.Level)}?{item.Text}");
}

根據不同block的位置、level關系,推出父子關系,使用 ?idpid 關聯

for?(var?i?=?0;?i?<?headings.Count;?i++)?{var?item?=?headings[i];item.Id?=?i;for?(var?j?=?i;?j?>=?0;?j--)?{var?preItem?=?headings[j];if?(item.Level?==?preItem.Level?+?1)?{item.Pid?=?j;break;}}
}

最后用遞歸生成樹結構

List<TocNode>??GetNodes(int?pid?=?-1)?{var?nodes?=?headings.Where(a?=>?a.Pid?==?pid).ToList();return?nodes.Count?==?0???null:?nodes.Select(a?=>?new?TocNode?{Text?=?a.Text,?Href?=?$"#{a.Text}",?Nodes?=?GetNodes(a.Id)}).ToList();
}

搞定。

4實現效果

把生成的樹結構打印一下

[{"Text":?"DjangoAdmin","Href":?"#DjangoAdmin","Tags":?null,"Nodes":?[{"Text":?"一些參考資料","Href":?"#一些參考資料","Tags":?null,"Nodes":?null}]},{"Text":?"界面主題","Href":?"#界面主題","Tags":?null,"Nodes":?[{"Text":?"SimpleUI","Href":?"#SimpleUI","Tags":?null,"Nodes":?[{"Text":?"一些相關的參考資料","Href":?"#一些相關的參考資料","Tags":?null,"Nodes":?null}]},{"Text":?"django-jazzmin","Href":?"#django-jazzmin","Tags":?null,"Nodes":?null}]},{"Text":?"定制案例","Href":?"#定制案例","Tags":?null,"Nodes":?[{"Text":?"添加自定義列","Href":?"#添加自定義列","Tags":?null,"Nodes":?[{"Text":?"效果圖","Href":?"#效果圖","Tags":?null,"Nodes":?null},{"Text":?"實現過程","Href":?"#實現過程","Tags":?null,"Nodes":?null},{"Text":?"擴展:添加鏈接","Href":?"#擴展:添加鏈接","Tags":?null,"Nodes":?null}]},{"Text":?"顯示進度條","Href":?"#顯示進度條","Tags":?null,"Nodes":?[{"Text":?"效果圖","Href":?"#效果圖","Tags":?null,"Nodes":?null},{"Text":?"實現過程","Href":?"#實現過程","Tags":?null,"Nodes":?null}]},{"Text":?"頁面上顯示合計數額","Href":?"#頁面上顯示合計數額","Tags":?null,"Nodes":?[{"Text":?"效果圖","Href":?"#效果圖","Tags":?null,"Nodes":?null},{"Text":?"實現過程","Href":?"#實現過程","Tags":?null,"Nodes":?[{"Text":?"admin.py","Href":?"#admin.py","Tags":?null,"Nodes":?null},{"Text":?"template","Href":?"#template","Tags":?null,"Nodes":?null}]},{"Text":?"參考資料","Href":?"#參考資料","Tags":?null,"Nodes":?null}]},{"Text":?"分權限的軟刪除","Href":?"#分權限的軟刪除","Tags":?null,"Nodes":?[{"Text":?"實現過程","Href":?"#實現過程","Tags":?null,"Nodes":?[{"Text":?"models.py","Href":?"#models.py","Tags":?null,"Nodes":?null},{"Text":?"admin.py","Href":?"#admin.py","Tags":?null,"Nodes":?null}]}]}]},{"Text":?"擴展工具","Href":?"#擴展工具","Tags":?null,"Nodes":?[{"Text":?"Django?AdminPlus","Href":?"#Django?AdminPlus","Tags":?null,"Nodes":?null},{"Text":?"django-adminactions","Href":?"#django-adminactions","Tags":?null,"Nodes":?null}]}
]

5完整代碼

我把這個功能封裝成一個方法,方便調用。

直接上GitHub Gist:https://gist.github.com/Deali-Axy/436589aaac7c12c91e31fdeb851201bf

接下來可以嘗試使用后端來渲染Markdown文章了~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281581.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281581.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281581.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

漢諾塔c語言源程序步驟,漢諾塔問題的算法分析及C語言演示程序的實現

摘要:該文對經典的“漢諾塔”問題進行了詳細的分析,并用C語言實現。通過問題的具體實現,使學習者了解問題的全過程,推廣到一般。關鍵詞:漢諾塔;遞歸;C語言中圖分類號:TP301.6文獻標識碼:A文章編號:1009-3044(2010)09-2130-02Algorithm Analysis and C Realization of Hanio Iss…

spring security xml配置詳解

security 3.x <?xml version"1.0" encoding"UTF-8"?> <beans:beans xmlns"http://www.springframework.org/schema/security" xmlns:beans"http://www.springframework.org/schema/beans" xmlns:xsi"http://www…

【Redis源碼分析】Redis命令處理生命周期

運營研發團隊 李樂 前言 本文主要講解服務器處理客戶端命令請求的整個流程&#xff0c;包括服務器啟動監聽&#xff0c;接收命令請求并解析&#xff0c;執行命令請求&#xff0c;返回命令回復等&#xff0c;這也是本文的主題“命令處理的生命周期”。 Redis服務器作為典型的事件…

博鰲直擊 | 區塊鏈在互聯網金融中扮演怎樣的角色?

雷鋒網3月24日報道&#xff0c;今日&#xff08;3月24日&#xff09;&#xff0c;第16屆博鰲亞洲論壇2017年年會在海南繼續進行中。據雷鋒網了解&#xff0c;在今日下午的數字貨幣與區塊鏈分論壇上&#xff0c;中國銀行前行長、中國互聯網金融協會區塊鏈工作組組長李禮輝講述了…

GDB調試qemu-kvm

GDB調試qemu-kvm 前面幾篇博文都是記錄一些kvm相關包編譯安裝及使用&#xff0c;但都沒深入去代碼看看。看源碼在配合上相關原理才能更好的理解kvm。但qemu-kvm的代碼量很多&#xff0c;對我來講直接看源碼收獲甚少&#xff0c;所以找了個調試工具——GDB來配合閱讀代碼。接下來…

c語言編譯錯誤 原文,C語言常見錯誤與警告

C語言常見錯誤與警告C語言常見錯誤與警告C語言常見錯誤&#xff1a;1 invalid type argument of ‘->’ (have ‘struct qstr_xid_element’)這種錯誤一般是沒有理解C中“->”與“.”用法的不同&#xff0c;“->”是指向結構體指針獲取結構體的成員變量時所用&#xf…

力爭營收渠道多樣化,Line 向自拍應用 Snow 投資 4500 萬美元

今年&#xff0c;在科技公司 IPO 市場不景氣的情況下&#xff0c;日本通信應用 Line順利進行了 IPO &#xff0c;目前正在尋求多樣化發展。今天, Line 宣布向自拍應用 Snow 投資 4500 萬美元(500 億韓元)。本次交易之后&#xff0c;Line 將獲得 Snow 25% 的股權。 Snow 常被稱為…

用.NET設計一個假裝黑客的屏幕保護程序

本文主要介紹屏幕保護程序的一些相關知識&#xff0c;以及其在安全方面的用途&#xff0c;同時介紹了如何使用 .NET 開發一款屏幕保護程序&#xff0c;并對核心功能做了介紹&#xff0c;案例代碼開源&#xff1a;https://github.com/sangyuxiaowu/HackerScreenSaver背景前幾天在…

【IntelliJ】IntelliJ IDEA常用設置及快捷鍵以及自定義Live templates

IntelliJ IDEA是一款非常優秀的JAVA編輯器&#xff0c;初學都可會對其中的一些做法感到很別扭&#xff0c;剛開始用的時候我也感到很不習慣&#xff0c;在參考了網上一些文章后在這里把我的一些經驗寫出來&#xff0c;希望初學者能快速適應它&#xff0c;不久你就會感覺到編程是…

復習Javascript專題(一):基本概念部分

一、數據類型 基本類型&#xff1a;Null Boolean String Undefined Number(NB SUN)引用類型&#xff1a;Array Function Object類型判斷&#xff1a;typeof 返回結果"undefined"&#xff08;未定義&#xff09; "boolean"(布爾值) "st…

c語言時鐘報告,C語言圖形時鐘課程設計實驗報告

C語言圖形時鐘課程設計實驗報告 目錄1.系統功能要求。2. 數據結構設計及說明。3.程序結構(畫流程圖) 。4.各模塊的功能。5.試驗結果(包括輸入數據和輸出結果) 。6.體會。7.參考文獻。8.附錄&#xff1a;程序清單及源程序。? 系統功能要求&#xff1a;在屏幕上顯示一個圖形時鐘…

微軟發布 2023 財年第一季度財報:營收達 501 億美元,同比增長 11%

北京時間 2022 年 10 月 26 日——微軟發布 2023 財年第一季度財報。財報顯示&#xff0c;截止到 2022 年 9 月 30 日&#xff1a;營收達到 501 億美元&#xff0c;增長 11%&#xff08;按固定匯率計算增長 16%&#xff09;運營收入為 215 億美元&#xff0c;增長 6%&#xff0…

《圖解CSS3:核心技術與案例實戰》——1.3節漸進增強

本節書摘來自華章社區《圖解CSS3&#xff1a;核心技術與案例實戰》一書中的第1章&#xff0c;第1.3節漸進增強&#xff0c;作者 大漠&#xff0c;更多章節內容可以訪問云棲社區“華章社區”公眾號查看 1.3 漸進增強第一次聽到“漸進增強”&#xff08;Progressive Enhancement…

阿里云云主機搭建網站攻略 - 云翼計劃

阿里云服務器&#xff08;云主機&#xff09;搭建網站攻略 - 云翼計劃 提示&#xff1a;此搭建攻略為2017版本&#xff0c;阿里云未跟新前。 最新搭建攻略請前往 Amaya丶夜雨博客 / 最新個人博客 https://www.amayaliu.cn 支持一下哦&#xff0c;謝謝。&#xff08;9.5一…

用c語言遞歸函數做掃雷,【C語言基礎學習---掃雷游戲】(包含普通版+遞歸煉獄版)...

/*******************///以下是源文件game.c內容/*******************/#include"game.h"//初始化棋盤的實現void InitBoard(char board[ROWS][COLS], int rows, int cols, char set){int i 0;int j 0;for (i 0; i < rows; i){for (j 0; j < cols; j){board…

記一次 .NET 某醫療器械 程序崩潰分析

一&#xff1a;背景 1.講故事前段時間有位朋友在微信上找到我&#xff0c;說他的程序偶發性崩潰&#xff0c;讓我幫忙看下怎么回事&#xff0c;上面給的壓力比較大&#xff0c;對于這種偶發性崩潰&#xff0c;比較好的辦法就是利用 AEDebug 在程序崩潰的時候自動抽一管血出來&a…

1251: 字母圖形 [水題]

1251: 字母圖形 [水題] 時間限制: 1 Sec 內存限制: 128 MB提交: 140 解決: 61 統計題目描述 利用字母可以組成一些美麗的圖形&#xff0c;下面給出了一個例子&#xff1a; ABCDEFG BABCDEF CBABCDE DCBABCD EDCBABC 這是一個5行7列的圖形&#xff0c;請找出這個圖形的規律&…

c語言 三角形三邊abc,C語言代碼輸入abc三個數,求一這3個數為邊長的三角形面積...

2011-01-04 回答#include #include #include #include #include int main(){float a 0.0;float b 0.0;float c 0.0;float s 0.0;double area 0.0;while(true){printf("input your date(a,b,c):");scanf("%f%f%f",&a,&b,&c);if(!isdigit((…

shell腳本中向hive動態分區插入數據

在hive上建表與普通分區表創建方法一樣&#xff1b; 1 CREATE TABLE dwa_m_user_association_circle(2 device_number string, 3 oppo_number string, 4 prov_id_oppo string, 5 area_id_oppo string, 6 dealer_oppo string, 7 short_call_nums bigint, 8 long3…

WPF效果第二百零二篇之TreeView帶連接線

前面文章中分享了TreeView支持多選;然而在項目上使用時,領導覺得不滿意:體現不了真正的從屬關系;既然領導都發話了;那就開整就行了;今天就再來個帶有連接線的TreeView效果:1、來看看TreeViewItem的Template:2、展開和收縮動畫:3、參考資料https://www.codeproject.com/tips/673…