ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用 Material for MkDocs 内置 Blog 插件搭建博客:从配置、写作到深度自定义

用 Material for MkDocs 内置 Blog 插件搭建博客:从配置、写作到深度自定义 用 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),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进