序文
StarBlog ブログは現在、 editor.md
フロントエンドでマークダウン記事をレンダリングするコンポーネントを使用していますが、このコンポーネントによって自動的に生成される ToC (コンテンツの目次) はあまり美しくありません。以前にツリー コンポーネントの BootStrap- TreeView を修正したので、これを使用したいと考えています目次を表示するツリーコンポーネント。
本来のエフェクトはこんな感じ
私の魔法改造の効果
先分析一波
まず、公式の例に従って、editor.md コンポーネントがどのようにマークダウンをレンダリングするかを見てください。
まずテキストエリアを作成し、そこにマークダウンを置きます
<div id="post-markdown-content" class="post-content">
<textarea style="display:none;">@Model.Content</textarea>
</div>
ディレクトリを置くdivもあります
<div id="post-toc-container"></div>
次に、js を使用してレンダリング メソッドを呼び出します。
let editorMdView = editormd.markdownToHTML("post-markdown-content", {
htmlDecode: true,
tocm: true, // Using [TOCM]
tocContainer: "#toc-container", // 自定义 ToC 容器层
emoji: true,
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
});
このようにして記事の内容と目次が出てきます。
最初に思ったのは、ディレクトリをレンダリングできるので、使用できるディレクトリツリー構造が必要だということでした。
その結果、このツリー構造をコンソールで 長い間console.log
見ることができませんでした
editormd.markdownToHTML
メソッドによって返されるデータは、単なる div 要素のオブジェクトです。
投げ始める
言葉が出ない、ソースコードを見るしかない
コンポーネント全体のソースコードはjsファイルになっていますが、幸い可読性は悪くありません~
メソッドの定義を直接検索し markdownToHTML
、3885 行目から開始して、その中の変数を見つけます markdownToC
。これが目的のものであるはずです。それを印刷して確認します。一般的な構造は次のとおりです。
[
{"text": "Node1", "slug": "node1", "level": 2},
{"text": "Django-Dev", "slug": "django-dev", "level": 3},
{"text": "Java-Dev", "slug": "java-dev", "level": 3},
{"text": "Spring-Dev", "slug": "spring-dev", "level": 3}
]
ツリー構造ではなく配列です
これは単にマークダウン ドキュメント全体を走査し、level
フィールドはタイトル タイプ、つまり #
番号に従って決定されます。
また、以前に変更したコンポーネントは Bootstrap-Treeview
レンダリングのためにツリー構造のオブジェクトを渡す必要があるため、さらに処理が必要です。
ハンドルツリー構造
最初はびっくりして、 editor.md
生成されたものを再帰に放り込んだだけでした
うまくいかなかった
その後、気が変わり、最初に配列を変更し、各項目に id と pid を追加しました。これにより、再帰的にツリーを生成するのがはるかに簡単になります~
最初にノード オブジェクトを定義します。これは Bootstrap-Treeview
使用する必要があるデータ構造です。
class TocNode {
constructor(text, href, tags, nodes) {
this.text = text
this.href = href
this.tags = tags
this.nodes = nodes
}
}
次に、 markdownToC
その作業をもう一度実行して、最上位ノードの pid を -1 に設定し、各ノードに 0 から順に ID を割り当てます。次に、各ノードの前でレベルが 1 未満のノードを探します。親ノード、pid を設定、完了しました~
let toc = markdownToC
for (let i = 0; i < toc.length; i++) {
let item = toc[i]
item.id = i
item.pid = -1
for (let j = i; j >= 0; j--) {
let preItem = toc[j]
if (item.level === preItem.level + 1) {
item.pid = j
break
}
}
}
ツリー構造を生成します。非常に単純で、多くを言う必要はありません。
function getNodes(pid = -1) {
let nodes = toc.filter(item => item.pid === pid)
if (nodes.length === 0) return null
return nodes.map(item => new TocNode(item.text, `#${item.text}`, null, getNodes(item.id)))
}
終わった〜
魔法の変化
次に、このアイデアに基づいて、コードのコピーをフォークして魔法の変更を加えます。
元のバージョンでは markdownToHTML
メソッドの実行直後に div 要素が返されますが、返された div 要素に 2 つの属性を追加してから div を返しました。
div.markdownToc = markdownToC
div.markdownTocTree = editormd.tocListToTree(markdownToC)
return div
このようにして、使用中に Bootstrap-Treeview
コンポーネントを簡単に統合できます。
使用法
まずはリリースしたNPMパッケージをインストールします
// 魔改的 editor.md 组件
npm i editor.md-ext
// 魔改的树形列表组件
npm i bootstrap5-treeview
ページにCSSを導入する
<link rel="stylesheet" href="~/lib/editormd/css/editormd.preview.css">
JSをインポートする
<!-- jQuery -->
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<!-- 树形列表组件 -->
<script src="~/js/bootstrap-treeview.js"></script>
<!-- editor.md 需要的依赖 -->
<script src="~/lib/editormd/lib/marked.min.js"></script>
<script src="~/lib/editormd/lib/prettify.min.js"></script>
<script src="~/lib/editormd/lib/raphael.min.js"></script>
<script src="~/lib/editormd/lib/underscore.min.js"></script>
<script src="~/lib/editormd/lib/sequence-diagram.min.js"></script>
<script src="~/lib/editormd/lib/flowchart.min.js"></script>
<script src="~/lib/editormd/lib/jquery.flowchart.min.js"></script>
<script src="~/lib/editormd/editormd.js"></script>
ディレクトリコンテナとしてdivを用意する
<div id="post-toc-container"></div>
記事のコンテンツを保存する div を用意し、Markdown コンテンツをこのテキストエリアに配置します。
<div id="post-markdown-content" class="post-content">
<textarea style="display:none;">@Model.Content</textarea>
</div>
レンダリングを有効にするための JS コードを作成します。
$(function () {
// 渲染文章
let editorMdView = editormd.markdownToHTML("post-markdown-content", {
htmlDecode: true,
tocm: true, // Using [TOCM]
emoji: true,
taskList: true,
tex: true, // 默认不解析
flowChart: true, // 默认不解析
sequenceDiagram: true, // 默认不解析
});
// 渲染目录
$('#post-toc-container').treeview({
data: editorMdView.markdownTocTree,
levels: 2,
enableLinks: true,
highlightSelected: false,
showTags: true,
})
})
ツリー リスト コンポーネントの使用法については、私の GitHub を参照してください。GitHub - Deali-Axy/bootstrap5-treeview: Tree View for Twitter Bootstrap5 - 魔法の修正の元のバージョンは、新しい Bootstrap5 バージョンに適応されています。