使用 MDX 为 Astro 中使用的每个标签自动生成页面

随着Astro 2.0的发布,Content Collections API变得可用。
这使得以类型安全的方式查询 Markdown/MDX 变得非常容易(还有更多,请务必阅读我上面链接的博文)。
对于我的博客来说,设置它真的很容易,我只需要将我的博客从移动/pages/blog/content/blog并添加一个/content/config.ts文件。
/content文件夹是用于资源库的保留文件夹。
/content/config.ts文件中,您为要创建的集合定义架构。
目前我只有1个收藏,即我的博客。
所以我创建了我的模式如下:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">defineCollection</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">astro:content</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">defineCollection</span><span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">schema</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">object</span><span style="color:var(--syntax-text-color)">({</span>
    <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">layout</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">array</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">()),</span>
    <span style="color:var(--syntax-name-color)">date</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">image</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">optional</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-text-color)">}),</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">collections</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

如您所见,tags是我所有博客的必需属性,幸运的是我从一开始就为每篇博文添加了标签。
在我的 MDX 中,标签在文件顶部定义如下:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>---
tags: ['javascript', 'edge', 'vercel'];
---
</code></span></span>

.astro现在我在我的配置中定义了博客集合,我可以开始使用我的文件中的数据。
我想为博客中使用的每个唯一标签创建一个单独的页面。
为了使这成为可能,我只是添加了一个文件/pages/blog/tags/[...slug].astro(这是一个动态路由)。
在这个文件中,我想从我的收藏中获取所有博客,找到唯一的标签,并为每个标签生成一个 URL。
getStaticPaths()函数将返回我希望在构建期间预呈现的 URL(因此该export const prerender = true;行)。

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-error-color)">---</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">prerender</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">slug</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">params</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">getCollection</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">astro:content</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blogs</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">tags</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">blogs</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">)</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">flat</span><span style="color:var(--syntax-text-color)">()</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">reduce</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">string</span><span style="color:var(--syntax-text-color)">]:</span> <span style="color:var(--syntax-name-color)">number</span> <span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">var</span> <span style="color:var(--syntax-name-color)">count</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">||</span> <span style="color:var(--syntax-literal-color)">0</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">count</span> <span style="color:var(--syntax-error-color)">+</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">{});</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getStaticPaths</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blogs</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">[...</span><span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-text-color)">Set</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blogs</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">flat</span><span style="color:var(--syntax-text-color)">())].</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">({</span>
    <span style="color:var(--syntax-name-color)">params</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-text-color)">}));</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">redirect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">/404</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span>
  <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">some</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">)</span>
<span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-literal-color)">0</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">redirect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">/404</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-error-color)">---</span>
</code></span></span>

我使用了一个.reduce()函数来计算每个标签可用的博客数量,因此我可以将其显示在标签页的顶部。
Content Collections 提供的 API 是函数getCollection(),它允许我获取我收藏中的所有博客blogs。如您所见,也可以向此函数传递一个过滤器函数,我过去只获取包含在第 22 行为其生成当前页面的标签的博客。实际渲染很简单,我现在可以
使用allBlogPostsWithTag变量并呈现博客文章。
由于slug匹配此页面生成的标签,我可以在我的标题/描述/..

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Layout</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-string-color)">`The Thomas Ledoux blog | </span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-string-color)">}</span>
  <span style="color:var(--syntax-name-color)">description</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-string-color)">`All blogs about </span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-string-color)">}</span>
<span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">section</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">h1</span> <span style="color:var(--syntax-name-color)">class</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text-center text-2xl font-bold mb-6"</span><span style="color:var(--syntax-text-color)">></span>
      All blogs about <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">h1</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Tags</span> <span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-text-color)">/></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span>
      <span style="color:var(--syntax-name-color)">class</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"grid sm:grid-cols-2 lg:grid-cols-3 gap-6 items-center auto-rows-min mt-4"</span>
    <span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span>
        <span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">i</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
          <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">remarkPluginFrontmatter</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">render</span><span style="color:var(--syntax-text-color)">();</span>

          <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">PostPreview</span>
              <span style="color:var(--syntax-name-color)">minutesRead</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">remarkPluginFrontmatter</span><span style="color:var(--syntax-text-color)">?.</span><span style="color:var(--syntax-name-color)">minutesRead</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-name-color)">index</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">i</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)">/></span>
          <span style="color:var(--syntax-text-color)">);</span>
        <span style="color:var(--syntax-text-color)">})</span>
      <span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">section</span><span style="color:var(--syntax-text-color)">></span>
<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-name-color)">Layout</span><span style="color:var(--syntax-text-color)">></span>
</code></span></span>

此标记页的结果将如下所示:

我必须说我真的很喜欢与 Astro 一起编写 Markdown/MDX,尤其是当他们使它变得如此简单时!源代码可以在Github

上找到。可以在此处 找到标签页的示例。

猜你喜欢

转载自blog.csdn.net/jascl/article/details/131304350
MDX
今日推荐