上周,我通过电子邮件帮助某人,我们开始讨论如何在Eleventy中支持 "草稿 "帖子。草稿文章,至少在本篇文章中,是指不应该在发布的网站上呈现的内容。它可能是一篇需要时间编辑的博文,也可能是作者需要时间咀嚼的内容。它可能被提交到资源库,但不应该在实际的网站上显示。我对这个问题做了一些调查,得出了几个不同的解决方案,我想与大家分享,但像往常一样,请让我知道你的想法或者你是如何完成同样的事情的。
在这个演示中,我使用了一个简单的博客应用程序,帖子都存储在一个posts 目录中。我有两个帖子,alpha.md 和beta.md ,我的意图是让beta.md 成为一个草稿。最初,每篇博客文章都包含title 和layout 的前述内容。好了,让我们开始吧!
迭代一
第一个,也是最简单的抑制内容的方法是使用permalink 的功能来禁止向磁盘写入。因此,给定一个我想在草稿模式下的帖子,我可以直接这样做:
---
title: beta
layout: main
permalink: false
---
this is beta
将permalink 设置为false将阻止文件被发布。又好又简单,对吗?但是,如果你使用一个目录数据文件来指定你的收藏,或getFilteredByGlob 呢?在这种情况下,即使模板没有被存储,它仍然会被视为集合的一部分。因此,举例来说,设想我们的posts 目录中有posts.11tydata.json 。
{
"tags":"posts"
}
你通常会这样做,以避免自己对每篇博客文章进行标记。如果你这样做了,然后遍历了collections.posts ,那么草稿文章就会显示出来。url 属性将是假的,但它仍然会显示出来。作为一个例子:
{% for post in collections.posts %}
a post: {{ post.url }}, title {{ post.data.title}}, tags: {{ post.data.tags }}<br/>
{% endfor %}
以及结果:
<h2>Posts</h2>
a post: /posts/alpha/, title alpha, tags: posts<br/>
a post: false, title beta, tags: posts<br/>
我对这个迭代的另一个问题是--虽然它半途而废--我不喜欢这样的事实:一个新的开发者可能不明白为什么我们要这样使用permalink 。是的,我很挑剔,但代码并不清楚它在这里要做什么。让我们把它变得更好。
迭代二
在第二次迭代中,我想修复前一个版本的两个问题。首先,我想用更好的前言来更清楚地表达我的意图,更重要的是,确保帖子的草稿不会显示在集合中。
首先,让我们从使用数据JSON文件切换到数据JavaScript文件,这样我们就可以使用一些代码。我把我的JSON文件重命名为posts.11tydata.js ,并使用了这个代码:
module.exports = {
eleventyComputed: {
permalink: data => {
if(data.draft) return false;
},
tags: data => {
if(!data.draft) return 'posts';
return '';
}
}
}
我根据前面事项中draft 的值,使permalink 的值是动态的。tags 的值也是动态的,这次只在draft 不被使用时将其设置为posts 。在beta.md ,我改成了这样:
---
title: beta
layout: main
draft: true
---
this is beta
这看起来很完美,但有趣的事情发生了。首先,permalink 完美地工作,beta.md 没有发布。但是,当我在collections.posts 上循环时--奇怪的是,没有任何东西被输出!事实上,请看这个:
<h2>posts</h2>
{% for post in collections.posts %}
a post: {{ post.url }}, title {{ post.data.title}}, tags: {{ post.data.tags }}<br/>
{% endfor %}
<h2>all</h2>
{% for post in collections.all %}
page: {{ post.url }}, title {{ post.data.title}}, tags: {{ post.data.tags }}<br/>
{% endfor %}
正如你所看到的,我在我的帖子和全局的all 集合上进行循环。在这两个地方,我输出了url,title, 和tags 。这是输出结果:
<h2>posts</h2>
<h2>all</h2>
page: /, title , tags: <br/>
page: /posts/alpha/, title alpha, tags: posts<br/>
page: false, title beta, tags: <br/>
所以,是的,我的非草稿文章被正确地标记了,但没有在集合中显示出来。我不知道该怎么想,可能这是个bug(发表后我会归档--更新--我在这里归档),但我采取了另一种方法。
在.eleventy.js ,我添加了一个自定义集合:
eleventyConfig.addCollection("blogPosts", function(collectionApi) {
return collectionApi.getFilteredByTag("posts");
});
你猜怎么着?这也没有用!这肯定是一个时间/鸡肉+鸡蛋/等类型的问题。最后,我改用了一个文件系统的解决方案:
eleventyConfig.addCollection("blogPosts", function(collectionApi) {
let initial = collectionApi.getFilteredByGlob("posts/*.md");
return initial.filter(i => {
return i.data.tags && i.data.tags === 'posts';
});
});
奇怪的是,在这种情况下,我能够得到我的帖子,Eleventy正确地处理了动态标签方面的问题,并正确地返回了一个经过过滤的非草稿帖子列表。我把我的 "博客文章显示 "逻辑切换到:
{% for post in collections.blogPosts %}
很完美!我把我的 "博客文章显示 "逻辑切换到:"完美!"。注意,你要确保你持续使用这个新的集合。因此,例如,如果你有一个RSS提要(你有,对吗?)或一个搜索界面,你要使用blogPosts ,而不是posts 。
理论上,你现在可以停止阅读了,但我也有另一个想法。
迭代三
如果你想拥有已发表的 "草稿 "文章,但不能从你的文章列表、RSS等链接到这些文章,会怎么样?这可以让你发布一个草稿,并让其他人看一下,以便审查。明确地说,你也可以只分享一个链接到你的资料库,但如果你想让一个非技术人员做审查,在你的网站背景下看到帖子,等等,那么发布,但不包括草稿,可能会有帮助。
我们可以通过简单地删除permalink 功能来支持这一点:
module.exports = {
eleventyComputed: {
tags: data => {
if(!data.draft) return 'posts';
return '';
}
}
}
至少在与我们的自定义集合相结合时,标签仍然是正确的,而且beta.md 将被写入文件系统。这意味着你可以随后与他人分享一个URL,以获得他们对内容的反馈。
作为最后的说明,你也可以用这一切来支持未来的帖子。也就是说,如果数据是在未来,就不要链接/发布。但是,你需要将其与一个预定的构建系统结合起来,以确保当帖子上线的时候,一个构建被启动。如果你不关心精确的时间,这可以用一个每日计划来完成。