ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Pelican 隐藏页面机制深度解析:从 `status: hidden` 测试样例到源码实现

Pelican 隐藏页面机制深度解析:从 `status: hidden` 测试样例到源码实现 Pelican 隐藏页面机制深度解析从status: hidden测试样例到源码实现【免费下载链接】pelicanStatic site generator that supports Markdown and reST syntax. Powered by Python.项目地址: https://gitcode.com/gh_mirrors/pe/pelican本文围绕 Pelican 静态站点生成器中的隐藏页面hidden page机制展开。隐藏页面是 Pelican 内容状态体系中的重要一环页面与文章照常生成 HTML 输出但不会出现在菜单、列表、索引或 Feed 中适合制作 404 错误页、未列出unlisted内容等场景。通过阅读本文你将掌握status元数据的四种取值及其差异、隐藏页面在生成器中的完整处理链路、reST/Markdown/HTML 三种格式下的标记写法以及如何在主题模板中访问隐藏内容。从一个测试样例认识隐藏页面仓库中的 pelican/tests/TestPages/hidden_page.rst 是 Pelican 用于验证隐藏页面功能的测试夹具全文只有 8 行却完整展示了隐藏页面的三个核心要素This is a test hidden page ########################## :status: hidden The quick brown fox jumped over the lazy dogs back. This page is hidden逐行拆解可以看到标题首行文本配合下方等长的#字符行是 reStructuredText 的文档标题语法对应页面元数据中的title状态声明:status: hidden是 reST 字段列表field list写法在 pelican/readers.py 中status元数据由METADATA_PROCESSORS处理值会经过strip()去空白后写入内容对象正文状态行之后的内容即页面正文会被渲染为 HTML 输出到生成站点中。正是这个看似简单的:status: hidden决定了该页面与普通页面的本质区别——它仍会被渲染输出但被隔离在正常的页面导航体系之外。Pelican 的内容状态体系published / hidden / draft / skip隐藏页面并非孤立设计它是 Pelican 内容状态机制的一部分。在 pelican/contents.py 中Page与Article两个核心类共同声明了完整的状态白名单class Page(Content): mandatory_properties (title,) allowed_statuses (published, hidden, draft, skip) default_status published default_template page class Article(Content): mandatory_properties (title, date) allowed_statuses (published, hidden, draft, skip) default_status published default_template article四种状态的含义在官方文档 docs/content.rst 中有明确说明状态输出行为索引与 Feed 行为published默认按*_SAVE_AS正常输出正常出现在所有索引、菜单、Feed 中hidden按*_SAVE_AS正常输出不进入菜单/页面列表不进入 tag、category、author 索引及主 Feeddraft输出到drafts/目录不出现在首页、分类页、标签页skip完全不处理、不输出不进入任何索引与 Feed值得注意的细节在 pelican/contents.py 的Content初始化逻辑中如果元数据中没有提供status会回退到类的default_status即published而 pelican/contents.py 的_has_valid_status()方法则负责校验状态合法性——若写入了白名单之外的状态值生成器会报错并跳过该文件Unknown status xxx for file xxx.rst, skipping it. (Not in (published, hidden, draft, skip))另外status的值会被统一转换为小写见 pelican/contents.py 的status属性 setter因此写Status: HIDDEN与status: hidden效果相同。生成器如何分拣隐藏页面源码级处理链路隐藏页面真正的分拣逻辑位于页面生成器 pelican/generators.py 的generate_context()方法中。核心代码如下if page.status published: all_pages.append(page) elif page.status hidden: hidden_pages.append(page) elif page.status draft: draft_pages.append(page) elif page.status skip: raise AssertionError(Documents with skip status should be skipped)处理流程可以概括为四个阶段读取与校验readers.read_file()读取源文件生成Page对象page.is_valid()校验标题等必填属性与状态合法性状态分拣按status将页面分别放入all_pages、hidden_pages、draft_pages三个列表skip状态的文件在读取阶段就通过SkipStub机制被安全跳过pelican/generators.py不会走到这里翻译与排序三个列表分别经过process_translations()处理多语言版本再按PAGE_ORDER_BY排序上下文注入self._update_context((pages, hidden_pages, draft_pages))将隐藏页面集合写入模板上下文供主题使用。文章生成器 pelican/generators.py 对Article执行了完全对称的分拣逻辑产生self.articles、self.hidden_articles、self.drafts三组集合。这里有一个容易被忽视的关键设计在 pelican/generators.py 的分类汇总循环中只有self.articles即published状态的文章会被登记到self.categories、self.tags和self.authors。注释原文为# only main articles are listed in categories and tags # not translations or hidden articles这正是隐藏文章不进入标签、分类、作者索引的源码依据。输出阶段隐藏页面依然会生成 HTML在generate_output()方法pelican/generators.py中页面生成器会把隐藏页面与普通页面、草稿页面一起遍历并调用writer.write_file()输出for page in chain( self.translations, self.pages, self.hidden_translations, self.hidden_pages, self.draft_translations, self.draft_pages, ): ... writer.write_file( page.save_as, ... )也就是说hidden与draft的本质区别在于输出路径与是否被列入索引而非是否渲染。这一点可以在测试输出产物中得到印证仓库中预生成的 pelican/tests/output/basic/pages/this-is-a-test-hidden-page.html 是一份完整、可访问的 HTML 页面标题为 This is a test hidden page并且正文中明确写道This is great for things like error(404) pages — Anyone can see this page but its not linked to anywhere!这句话精辟地概括了隐藏页面的设计用途任何访问者都可以看到它但站点内没有任何地方会链接到它。隐藏页面与草稿页面的区别隐藏页面与草稿页面经常被混淆二者最直观的区别体现在输出路径上。以页面为例对比 docs/settings.rst 中的相关设置设置项默认值适用状态PAGE_URL/PAGE_SAVE_ASpages/{slug}.htmlpublished与hiddenDRAFT_PAGE_URL/DRAFT_PAGE_SAVE_ASdrafts/pages/{slug}.htmldraftDRAFT_PAGE_LANG_URL/DRAFT_PAGE_LANG_SAVE_ASdrafts/pages/{slug}-{lang}.htmldraft非默认语言对应的文章侧设置为ARTICLE_SAVE_AS默认{slug}.html与DRAFT_URL/DRAFT_SAVE_AS默认drafts/{slug}.html见 docs/settings.rst。这背后的实现机制在 pelican/contents.py 中Page._expand_settings()会根据状态切换 URL 配置的类别名——def _expand_settings(self, key: str) - str: klass draft_page if self.status draft else None return super()._expand_settings(key, klass)即状态为draft时使用DRAFT_PAGE_*系列设置输出到drafts/pages/否则使用PAGE_*系列设置。Article侧的逻辑与之对应pelican/contents.pydraft状态切换为DRAFT_*设置其余状态统一按ARTICLE_*设置输出。因此隐藏页面与普通页面共用 URL 与输出路径只是被移出了菜单与索引。另外草稿文章还有一个特别行为当WITH_FUTURE_DATES为False且文章日期在未来时Article.__init__会自动将状态改为draft见 pelican/contents.py而draft状态且未提供date的文章会被赋予最大日期值保证它排序时始终靠后pelican/contents.py。隐藏文章Hidden Posts未列出的文章隐藏状态同样适用于文章。官方文档 docs/content.rst 对隐藏文章有专门说明Like pages, posts can also be marked ashiddenwith theStatus: hiddenattribute. Hidden posts will be output toARTICLE_SAVE_ASas expected, but are not included by default in tag, category, and author indexes, nor in the main article feed. This has the effect of creating an unlisted post.即隐藏文章会正常输出到{slug}.html但默认不进入标签、分类、作者索引和主文章 Feed效果相当于博客平台的私密/未列出文章——只有持有直接 URL 的人才能访问。仓库中的测试样例 pelican/tests/content/article_hidden.md 展示了 Markdown 格式的隐藏文章写法Title: Hidden article Date: 2012-10-31 Status: hidden This is some unlisted content.作为对比skip状态的文章如 pelican/tests/content/article_skip.md 中的Status: skip会被完全忽略既不处理也不输出连生成的 HTML 都不会有。不同格式下的隐藏标记写法status元数据的书写方式随内容格式而异Pelican 对 reST、Markdown、HTML 三种格式都提供了支持reStructuredText字段列表见 pelican/tests/TestPages/hidden_page.rstMy hidden page title #################### :status: hidden Page body here.Markdown键值对见 pelican/tests/TestPages/hidden_page_markdown.mdtitle: This is a markdown test hidden page status: hidden Page body here.HTMLmeta 标签Pelican 支持从 HTML 文件的meta namestatus contenthidden /中读取元数据机制见 docs/content.rst 对 HTML 阅读器的说明。此外如果希望站点内所有内容默认都以某种状态发布可以在pelicanconf.py中配置DEFAULT_METADATAdocs/content.rstDEFAULT_METADATA { status: draft, }这样未显式声明状态的文章都会成为草稿只有显式写上Status: published才会公开——适合防止误发布未完成内容。与自定义模板组合hidden template隐藏状态还可以与template元数据自由组合。测试夹具 pelican/tests/TestPages/hidden_page_with_template.rst 演示了这一点This is a test hidden page with a custom template ################################################# :status: hidden :template: custom The quick brown fox jumped over the lazy dogs back. This page has a custom template to be called when rendered当页面同时声明:status: hidden与:template: custom时Pelican 会以custom.html模板渲染该隐藏页面。从测试断言 pelican/tests/test_generators.py 可以看到该页面被正确归类为[This is a test hidden page with a custom template, hidden, custom]——即状态为 hidden、模板为 custom。这为用站点主题风格渲染 404 错误页之类的场景提供了直接支持。在主题模板中访问隐藏内容隐藏内容对主题作者同样是可用的。PagesGenerator.generate_context()会执行self._update_context((pages, hidden_pages, draft_pages))将三组页面集合都注入 Jinja2 上下文文章侧同理注入articles、hidden_articles、draftspelican/generators.py。这一能力在项目变更记录docs/changelog.rst 中 Make hidden pages available in context 条目中被明确列为历史功能。这意味着你可以在base.html或page.html等模板中自行引用隐藏内容例如在 404 页面里列出所有隐藏页面或在站点地图模板中主动包含它们{% for hidden in hidden_pages %} lia href{{ SITEURL }}/{{ hidden.url }}{{ hidden.title }}/a/li {% endfor %}默认情况下主题不会自动渲染这些内容但上下文中的可用性给了主题作者完全的自主权。测试验证隐藏页面行为如何被保障隐藏页面的行为有完整的自动化测试覆盖。在 pelican/tests/test_generators.py 的测试中测试套件以pelican/tests/TestPages为内容目录实例化PagesGenerator然后分别取出generator.pages、generator.hidden_pages、generator.draft_pages进行断言hidden_pages_expected [ [This is a test hidden page, hidden, page], [This is a markdown test hidden page, hidden, page], [This is a test hidden page with a custom template, hidden, custom], ] draft_pages_expected [ [This is a test draft page, draft, page], [This is a markdown test draft page, draft, page], [This is a test draft page with a custom template, draft, custom], ]该测试同时验证了三件事隐藏页面被正确分拣到hidden_pages而非pages草稿页面被正确分拣到draft_pages两者都被注入contextcontext[hidden_pages]、context[draft_pages]。文章侧的等价测试见同一文件中的test_articles_hiddenpelican/tests/test_generators.py断言隐藏文章被收集到generator.hidden_articles。典型使用场景总结结合官方文档说明与仓库测试产物隐藏页面/文章适合以下场景404 错误页用站点主题渲染一个风格统一的 404 页面直接通过 Web 服务器配置指向该页面无需出现在导航中docs/content.rst 明确提及 making error pages that fit the generated theme of your site未列出的文章为特定受众提供私密分享链接文章正常输出但不出现在 Feed、标签、分类和作者索引中预发布页面尚未准备好的着陆页或功能说明页先保持hidden正式发布时改为published即可配合模板的自定义页面结合template元数据为隐藏页面指定独立渲染模板。最后需要提醒一点hidden状态只影响是否被站点链接引用并不等于安全保护——隐藏页面依然会被原样生成到输出目录任何拿到直接 URL 的人都能访问。如果需要真正不可访问的内容应使用skip状态或直接在pelicanconf.py中配置*_EXCLUDE排除相关文件。【免费下载链接】pelicanStatic site generator that supports Markdown and reST syntax. Powered by Python.项目地址: https://gitcode.com/gh_mirrors/pe/pelican创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表