
用 Material for MkDocs 內置 Blog 插件搭建博客從配置、寫作到深度自定義【免費下載鏈接】mkdocs-materialDocumentation that simply works項目地址: https://gitcode.com/GitHub_Trending/mk/mkdocs-materialMaterial for MkDocs本倉庫自 9.2.0 起內置了獨立的 blog 插件讓你可以在現有文檔站點中旁掛一個博客也可以將站點完全改造成純博客模式——歸檔頁、分類頁、文章 slug、分頁全部自動生成你只需要專注于寫作內容本身。讀完本文你將掌握插件的完整配置項、front matter 元數據規范、RSS 訂閱接入以及如何通過源碼級的機制視圖、摘要、meta 默認值、模板覆蓋把博客打磨成你想要的樣子。一、內置 blog 插件的工作原理blog 插件實驗性特性標記為experimental的核心思路是掃描一個約定的posts目錄把其中的 Markdown 文件當作文章再自動生成若干視圖View。視圖是插件自動生成的頁面包括博客入口頁即blog/index.md按日期倒序列出所有文章的分頁視圖歸檔頁Archive按時間區間默認按年份聚合文章的頁面分類頁Category按分類聚合文章的頁面。從源碼看插件在on_files事件material/plugins/blog/plugin.py中以-50的優先級盡量晚地執行目的是讓其他插件有機會先生成文章或視圖。它通過_resolve_posts遍歷docs下的所有文檔頁篩選出位于 posts 目錄中的文件再調用_resolve_post計算其最終 URL 并創建Post對象隨后按(pin, date.created)降序排序置頂優先、日期新者在前并依次生成歸檔、分類與作者主頁視圖。默認的目錄結構如下缺失的目錄或文件會自動創建. ├─ docs/ │ └─ blog/ │ ├─ posts/ │ └─ index.md └─ mkdocs.ymlposts目錄純粹用于組織文章它不會出現在文章 URL 中——URL 完全由post_url_format控制。此外插件聲明了supports_multiple_instances True意味著可以配置多個 blog 插件實例來管理多個博客目錄。二、把博客接入現有文檔基礎配置啟用插件只需要在mkdocs.yml中注冊它無需 pip 安裝plugins: - blog導航nav的兩種處理方式如果你的mkdocs.yml沒有定義nav那么什么都不用做——blog 插件會自動把入口頁、歸檔和分類掛到自動生成的導航中on_nav事件負責把歸檔/分類/作者主頁作為 section 掛載到入口頁之后見 plugin.py。如果你自定義了nav則只需且必須把博客入口頁加進去不要手動添加單篇文章nav: - index.md - Blog: - blog/index.md歸檔、分類等生成的頁面會自動作為該 section 的子項出現。導航項的名字如Blog、News可以隨意起但index.md的路徑必須與blog_dir一致。若使用 section index 風格可參考 導航設置。三、純博客模式Blog only如果你只需要一個純博客、完全不需要文檔可以把blog_dir指向docs根目錄此時posts目錄直接位于docs/下. ├─ docs/ │ ├─ posts/ # 注意posts 直接位于 docs 根下沒有中間的 blog 目錄 │ ├─ .authors.yml │ └─ index.md └─ mkdocs.ymlplugins: - blog: blog_dir: . # 詳見插件文檔中的 blog_dir 說明這樣文章 URL 就從/blog/post_slug變成/post_slug。四、接入 RSS 訂閱blog 插件與 RSS 插件無縫集成注意外部鏈接僅作背景說明本節配置以倉庫文檔為準。先安裝pip install mkdocs-rss-plugin然后在mkdocs.yml中注冊并配置plugins: - rss: match_path: blog/posts/.* # (1)! date_from_meta: as_creation: date categories: - categories - tags # (2)!match_path用正則過濾要進入 feed 的 URL這里表示只有博客文章進入訂閱想同時把文章的categories和tags作為 feed 分類就把兩者都列出來。RSS 相關配置項速覽enabled默認true是否啟用插件。本地構建想提速時可以用環境變量關閉plugins: - rss: enabled: !ENV [CI, false]match_path默認.*指定哪些頁面進入 feed如上例只收錄blog/posts/.*。date_from_meta默認無指定用 front matter 的哪個字段作為 feed 的創建日期推薦使用dateplugins: - rss: date_from_meta: as_creation: datecategories默認無指定哪些 front matter 字段作為 feed 分類同時使用分類與標簽時兩者都加。comments_path默認無指定評論錨點接入評論系統后使用plugins: - rss: comments_path: #__commentsMaterial for MkDocs 會自動向站點注入必要的元數據讓瀏覽器和訂閱器可以自動發現 RSS feed。需要注意RSS 插件的其他配置項不屬于Material for MkDocs 官方支持范圍使用后果自負。五、寫第一篇文章front matter 全解析插件不假設 posts 目錄內有任何特定結構文章可以隨意組織在嵌套文件夾中. ├─ docs/ │ └─ blog/ │ ├─ posts/ │ │ └─ hello-world.md # 位置隨意URL 由 post_url_format 與標題、日期決定 │ └─ index.md └─ mkdocs.yml新建hello-world.md并寫入--- draft: true # (1)! date: 2024-01-31 # (2)! categories: - Hello - World --- # Hello world! ...標記為草稿draft后索引頁的文章日期旁會出現紅色標記正式構建時草稿不會進入輸出。該行為可通過draft配置改變例如在部署預覽時渲染草稿見 drafts 與draft。如果想提供多個日期可以用字典語法從而定義最后更新時間及更多可放進模板的自定義日期--- date: created: 2022-01-31 updated: 2022-02-02 --- # Hello world!注意創建日期必須寫在date.created因為每篇文章都必須有創建日期——從源碼看DateDict在初始化時就直接讀取data[created]并暴露為屬性structure/options.py而PostDate選項會把標量日期自動歸一化為{ created: ... }字典缺失時直接拋錯。文章 front matter 由Post類的構造函數解析structure/init.py它讀取文件后先匹配 YAML front matter要求必須存在元數據用 SafeLoader 解析再與PostConfig的合法鍵取交集后校驗。這也解釋了為什么插件不接受 MkDocs 的 MultiMarkdown 語法——它只信任標準的 YAML front matter。啟動本地預覽服務器后你會看到第一篇文章同時歸檔頁與分類頁已經自動生成好了。草稿的三種控制方式BlogConfig中與草稿相關的默認值為config.pydraft false、draft_on_serve true、draft_if_future_date false。其行為在_is_excluded中實現plugin.py正式構建時排除草稿mkdocs serve時由于on_config會把draft置為true草稿會正常渲染方便本地預覽若開啟draft_if_future_date則創建日期在未來UTC 時間比較的文章會被自動視為草稿適合提前排期發布。六、為文章添加摘要、作者、分類與標簽添加摘要Excerpt博客索引、歸檔頁和分類頁既可以列出文章全文也可以只顯示摘要。在文章前幾段之后插入!-- more --分隔符即可# Hello world! Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa. !-- more -- ...生成索引時分隔符之前的全部內容會被自動提取為摘要讀者可以先預覽再決定是否點進去。從源碼看Excerpt.render會先用# 標題補全摘要內容保證標題可點擊跳轉渲染 HTML 后按分隔符切分分隔符之后的部分存入more屬性structure/init.py。分隔符可通過post_excerpt_separator修改也可用post_excerpt設為required強制每篇文章必須定義摘要否則構建直接報錯。添加作者在博客目錄下創建.authors.yml路徑由authors_file控制默認{blog}/.authors.ymlauthors: squidfunk: name: Martin Donath description: Creator avatar: https://github.com/squidfunk.png該文件把作者標識符這里是squidfunk與作者信息關聯起來。從 author.py 看每個作者支持name、description、avatar、slug、url五個字段后兩者可選。_resolve_authors會解析并校驗該文件格式非法或字段缺失都會以PluginError的形式友好報錯。然后在文章 front matter 中用authors屬性引用一個或多個作者--- date: 2024-01-31 authors: - squidfunk --- # Hello world! ...每個作者的小型資料卡會渲染在文章左側欄以及索引頁的摘要中。文章里引用了.authors.yml中不存在的作者標識符時構建會中止并提示Couldnt find author ...見 plugin.py。添加作者主頁作者檔案頁從 9.7.0 起可以開啟作者主頁authors_profiles: true為每個作者生成獨立頁面plugins: - blog: authors_profiles: true開啟后插件通過_generate_profiles為每個出現過的作者生成一個 Profile 視圖默認 URL 格式為author/{slug}config.py按時間倒序列出該作者的全部文章。如果與自定義索引頁結合你可以為每個作者寫一段簡介、社交鏈接等任意 Markdown 內容文章列表會自動追加在該頁內容之后。添加分類分類是給文章做主題分組的利器可以讓讀者按主題瀏覽全部相關文章。在 front matter 的categories屬性中聲明--- date: 2024-01-31 categories: - Hello - World --- # Hello world! ...為避免手滑打錯分類名可以在mkdocs.yml中用categories_allowed定義允許的分類白名單plugins: - blog: categories_allowed: - Hello - World一旦文章使用了白名單之外的分類構建就會中止_generate_categories中會拋出category ... not in allow list錯誤見 plugin.py。添加標簽分類之外blog 插件還與內置 tags 插件集成。在 front matter 的tags屬性中聲明標簽后文章會自動出現在標簽索引頁上--- date: 2024-01-31 tags: - Foo - Bar --- # Hello world! ...與普通頁面一致標簽渲染在主標題上方標簽索引頁只以標題鏈接文章。自定義 slugslug 是 URL 中對文章標題的簡短描述默認自動生成也可以用slug屬性顯式覆蓋--- slug: hello-world --- # Hello there world! ..._format_path_for_post會優先使用 front matter 中的slug否則用post_slugify函數處理標題生成plugin.py。slug 化函數與分隔符分別由post_slugify默認pymdownx.slugs.slugifyUnicode 友好能較好處理各語言和post_slugify_separator默認-控制。添加相關鏈接從 9.6.0 起可以用links屬性在文章左側欄加入進一步閱讀區塊引導讀者跳轉到站內其他頁面--- date: 2024-01-31 links: - plugins/search.md - insiders/how-to-sponsor.md --- # Hello world! ...links完全復用mkdocs.yml中nav的語法因此可以設置顯式標題、加入外部鏈接、甚至嵌套--- date: 2024-01-31 links: - plugins/search.md - insiders/how-to-sponsor.md - Nested section: - External link: https://example.com - setup/setting-up-site-search.md --- # Hello world! ...更進一步鏈接甚至可以帶錨點跳轉到文檔的特定小節插件解析錨點后會把錨點標題自動設置為該相關鏈接的副標題。注意所有鏈接必須像nav一樣相對于docs_dir。從源碼看_generate_links會遍歷links中的每個條目含嵌套 Section 遞歸對內部鏈接解析目標文件找不到文件會告警目標是資產則直接替換為目標 URL目標是頁面則轉換為Reference保留頁面標題、URL 與元數據帶錨點時會到目標頁的目錄樹中查找對應錨點plugin.py。文章與文章、文章與頁面的互鏈文章 URL 是動態計算的但插件會保證所有從文章出發、或指向文章的鏈接都正確。要鏈接到某篇文章直接使用 Markdown 文件路徑鏈接必須相對Hello World!從文章鏈回某個頁面如博客索引同理[Blog](https://link.gitcode.com/i/34de90a87da6a21bd4e88b64c5d335e8)posts目錄內的所有資源文件在構建時會拷貝到blog/assets目錄on_files中會重寫這些媒體文件的目標路徑與 URL見 plugin.py當然你也可以引用posts目錄之外、位于文檔其他位置的資源。置頂文章從 9.7.0 起可以用pin屬性把文章釘在博客索引頁、以及它所屬的歸檔頁與分類頁的頂部--- date: 2024-01-31 pin: true --- # Hello world! ...多篇置頂文章按創建日期排序創建日期最新的一篇在最前其余置頂文章按時間倒序排列這正是on_files中排序鍵為(pin, date.created)的原因。設置閱讀時間啟用post_readtime默認true后插件會自動計算每篇文章的預計閱讀時間并渲染在文章與摘要中。不過自動計算有時不夠準確或產生奇怪的數字此時可以用readtime屬性顯式覆蓋--- date: 2024-01-31 readtime: 15 --- # Hello world! ...設置后自動計算將被禁用on_page_content中僅當readtime未顯式設置時才調用計算函數見 plugin.py。閱讀時間算法位于 readtime/init.py按\W切分提取詞數除以每分鐘閱讀詞數默認265可通過post_readtime_words_per_minute調整再為每張圖片附加遞減的額外秒數從 12 秒遞減到 3 秒最后向上取整為分鐘。警告中日韓文字當前的閱讀時間計算沒有考慮中文、日文、韓文的字符分詞因此這些語言的文章閱讀時間可能不準確官方計劃在未來加入支持。在支持落地前請使用readtime屬性手動設置閱讀時間。七、用 meta 插件統一設置默認 front matter文章多了以后每篇都重復聲明作者、分類會很冗余。內置的 meta 插件9.6.0 起實驗性允許按目錄設置默認 front matter把文章按分類或作者分組然后在對應目錄放一個.meta.yml. ├─ docs/ │ └─ blog/ │ ├─ posts/ │ ├─ .meta.yml # 也可以放在 posts 下的任意嵌套目錄中 │ └─ index.md └─ mkdocs.yml.meta.yml中可以定義所有對文章合法的 front matter 屬性例如authors: - squidfunk categories: - Hello - World順序很重要meta插件必須定義在blog插件之前默認值才會被 blog 插件正確拾取plugins: - meta - blog從源碼看Post構造時會主動查找material/meta插件實例并提前調用它的on_page_markdown來合并 meta 文件中的元數據——這是博客文章能在on_files階段就拿到 meta 默認值的唯一途徑structure/init.py。.meta.yml中的列表與字典會和文章自身定義的 front matter合并并去重因此你可以在.meta.yml定義公共屬性再在每篇文章里追加或覆蓋個別屬性。八、在博客中添加靜態頁面除了文章還可以把普通頁面列進nav中作為博客的靜態頁面所有自動生成的索引會附加在最后一個指定頁面之后。例如為博客增加一個作者頁面nav: - Blog: - blog/index.md - blog/authors.md九、自定義歸檔與分類索引頁從 9.6.0 起如果你想給自動生成的歸檔頁或分類頁添加自定義內容比如在文章列表之前寫一段分類介紹可以手動創建插件本來會生成的那個頁面文件. ├─ docs/ │ └─ blog/ │ ├─ category/ │ │ └─ hello.md # 先在文章中加好分類再按插件生成的 URL 路徑創建文件 │ ├─ posts/ │ └─ index.md └─ mkdocs.yml最省事的做法是先給文章加上分類啟動一次構建拿到插件生成的 URL然后在blog_dir對應的位置創建同名文件。上圖基于默認配置若你修改了以下配置項路徑也要相應調整blog_dircategories_url_formatcategories_slugify在新文件里可以寫任意內容或設置該頁的 front matter例如修改頁面描述--- description: Nullam urna elit, malesuada eget finibus ut, ac tortor. --- # Hello ...該分類下的全部文章摘要會自動追加在頁面內容之后。_generate_categories會檢測到已存在的同名文件并直接復用為 Category 視圖plugin.py。十、覆蓋博客模板blog 插件建立在與 Material for MkDocs 相同的模板體系之上因此可以像平時一樣通過主題擴展覆蓋博客用到的全部模板。插件新增了以下兩個模板blog.html—— 博客、歸檔、分類索引頁模板倉庫內位于 material/templates/blog.htmlblog-post.html—— 文章頁模板倉庫內位于 material/templates/blog-post.htmlPost與View構造時會分別把默認模板設為blog-post.html與blog.htmlstructure/init.pyPost還會默認在hide中追加navigation即文章頁默認隱藏導航。文章與視圖的渲染上下文如posts、pagination對象、date/url模板過濾器由on_page_context與on_env注入覆蓋模板時可以充分利用這些變量plugin.py。十一、常用配置速查摘自插件配置類以下默認值均直接取自 config.py 中的BlogConfig可在mkdocs.yml的blog條目下按需覆蓋分組配置項默認值說明通用blog_dirblog博客目錄相對docs_dir通用blog_tocfalse是否在視圖中用目錄顯示文章標題文章post_dir{blog}/posts文章存放目錄支持{blog}占位符文章post_date_formatlong文章日期顯示格式babel 短碼或模式串文章post_url_date_formatyyyy/MM/dd文章 URL 中的日期格式文章post_url_format{date}/{slug}文章 URL 模板占位符有categories/date/slug/file文章post_excerptoptional摘要是否必須required時缺少分隔符會報錯文章post_excerpt_separator!-- more --摘要分隔符文章post_readtimetrue是否自動計算閱讀時間文章post_readtime_words_per_minute265每分鐘閱讀詞數歸檔archivetrue是否生成歸檔頁歸檔archive_url_formatarchive/{date}歸檔頁 URL 模板分類categoriestrue是否生成分類頁分類categories_url_formatcategory/{slug}分類頁 URL 模板分類categories_allowed[]分類白名單越界即構建失敗作者authorstrue是否啟用作者系統作者authors_file{blog}/.authors.yml作者信息文件路徑作者authors_profilesfalse是否生成作者主頁作者authors_profiles_url_formatauthor/{slug}作者主頁 URL 模板分頁paginationtrue是否啟用分頁分頁pagination_per_page10每頁文章數分頁pagination_url_formatpage/{page}分頁 URL 模板草稿draftfalse構建時是否渲染草稿草稿draft_on_servetrue本地預覽時是否渲染草稿草稿draft_if_future_datefalse是否把未來日期的文章視為草稿分頁、目錄相關配置還支持archive_*、categories_*、authors_profiles_*前綴的覆蓋版如archive_pagination_per_page未顯式設置時自動繼承全局值_config_pagination等函數實現見 plugin.py。小結內置 blog 插件把文章管理從你的工作清單中整個劃掉了你只要把 Markdown 文件放進posts目錄、寫好 front matter歸檔、分類、分頁、作者主頁、RSS、草稿管理全部自動完成。再疊加 meta 插件的目錄級默認值、自定義索引頁與模板覆蓋博客既能作為文檔站點的旁掛模塊也能獨立成站。你可以參考本倉庫自己的博客docs/blog 及 docs/blog/posts作為真實示例——它正是用這個內置插件構建的。【免費下載鏈接】mkdocs-materialDocumentation that simply works項目地址: https://gitcode.com/GitHub_Trending/mk/mkdocs-material創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考