支持Eleventy中的博客文章草案(附代码示例)

137 阅读5分钟

上周,我通过电子邮件帮助某人,我们开始讨论如何在Eleventy中支持 "草稿 "帖子。草稿文章,至少在本篇文章中,是指不应该在发布的网站上呈现的内容。它可能是一篇需要时间编辑的博文,也可能是作者需要时间咀嚼的内容。它可能被提交到资源库,但不应该在实际的网站上显示。我对这个问题做了一些调查,得出了几个不同的解决方案,我想与大家分享,但像往常一样,请让我知道你的想法或者你是如何完成同样的事情的。

在这个演示中,我使用了一个简单的博客应用程序,帖子都存储在一个posts 目录中。我有两个帖子,alpha.mdbeta.md ,我的意图是让beta.md 成为一个草稿。最初,每篇博客文章都包含titlelayout 的前述内容。好了,让我们开始吧!

迭代一

第一个,也是最简单的抑制内容的方法是使用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,以获得他们对内容的反馈。

作为最后的说明,你也可以用这一切来支持未来的帖子。也就是说,如果数据是在未来,就不要链接/发布。但是,你需要将其与一个预定的构建系统结合起来,以确保当帖子上线时候,一个构建被启动。如果你不关心精确的时间,这可以用一个每日计划来完成。