捨棄 create-react-app 之餘還架了個 astro blog 昭告天下:讀取 .md

根據官方文件,開發者只要根據 frontmatter YAML 以及 markdown syntax 來撰寫 .md 內容,就能直接借用 astro 內附的 markdown 編譯功能來把部落格文章轉為結構穩當的靜態網站。

今天會來簡單介紹在 astro 撰寫 .md 時的注意事項。

關於 md 檔

首先來在 ./src/pages 資料夾中新增一個 hello-world.md 檔案,結構如下:

---
<!--- 在兩組 `---` 之間的是 frontmatter 區塊 -->
layout:
title:
date:
---

<!--- 在第二組 `---` 之後的是文章本體區塊 -->

## 標題

內文 ⋯⋯

frontmatter/meta 區

除了常見的 title / date / tag 等「常見的文章 meta 資訊外」,astro 允許開發者在 .md frontmatter 區塊使用 layout 這個特殊關鍵字:

---
title: 鐵人賽 Modern Web 組「捨棄 create-react-app 之餘還架了個 astro blog 昭告天下」第 19 天
date: 2023-09-07 19:29:09
tag:
  - [2023鐵人賽]
banner: /2023/ithome-2023-19/elisa-calvet-b-S3nUOqDmUvc-unsplash.jpg
summary: 部落格的基本單位就是文章,今天就來看看 astro 如何處理 .md 檔案吧
draft: true
---

上方 .md frontmatter 代表的意義是:對這篇文章套用指定的 astro 元件 @Components/pages/SinglePostLayout.astro(提醒:實際路徑為 ./src/components/pages/SinglePostLayout.astro)。

另外,這篇文章其餘的 meta 資訊包含 title / date / tag / banner / summary / draft 六個項目。

文章本體區

astro 會把位於此處的內容轉為對應的 html 元件。開發者寫文時只要專注於內容與結構編排,不需要額外煩惱轉譯為靜態網站內容的問題。

提醒:在 .md 中引用圖片、影片等靜態內容時,須將檔案放置於 ./public 中再行引用。

![這裡是圖片 alt 文字內容](/image/hello-world.jpg)

以上在做的事情即是「引用位於 ./public/image 資料夾中的 hello-world.jpg 圖片」。注意不需要在靜態檔案的路徑中包含 ./public 資料夾。

關於 layout 元件

一個 astro 元件基本上會有 Component Script 與 Component Template 兩個部分。而以 .md 中指定的排版元件 SinglePostLayout 來說,它會包含以下內容:

---
// Component Script

interface Post {
  title: string;
  date: Date;
  tag: string[];
}

interface Props {
  frontmatter: Post;
}

const { frontmatter } = Astro.props;
---

<!-- Component Template (HTML + JS Expressions) -->
<div class="post-container">
  <h1>{frontmatter.title}</h1>
  <div class="info">
    <span>{frontmatter.date}</span>
    <span class="tag-container"
      >{frontmatter.tag.map((tag) => <span>{tag}</span>)}</span
    >
  </div>
  <slot />
</div>

Script 部分

根據官方文件,我們知道可以透過 Astro.props.frontmatter 取得我們在 .md frontmatter 區塊設定好的 meta 內容:

Specific properties are then available to the layout component through Astro.props. For example, you can access frontmatter properties through Astro.props.frontmatter.

官方定義好的 Astro.props 完整內容可參考 Markdown Layout Props

但在這個元件中,為了避免 TypeScript 報錯,我選擇重新定義 interface Props 來覆寫 astro 官方型別,這樣在 Template 部分才能順利取得 (markdown) Generated values 的內容(即 interface Post 中列出項目)。

Template 部分

我在這裡取出每篇文章的標題(frontmatter.title)放到 h1 中,並且透過 span 元件顯示發文日期(frontmatter.date)以及標籤(frontmatter.tag)。

而重點來了,整篇 .md 文章(已經結構化)的內容都會被傳入 <slot /> 元件裡面:

astro docs: A typical layout for Markdown or MDX pages includes the frontmatter prop to access the Markdown or MDX page’s frontmatter and other data, and a default <slot /> to indicate where the page’s Markdown/MDX content should be rendered.

沒錯,一個負責渲染 markdown 文章內容的 astro layout 只需要這些要素就能正常運作了。

總結

完成以上內容後,可開啟本地伺服器並移動到 localhost:4321/hello-world,這時你應該能看到被轉為 html 的 hello-world.md 內容。

現在你知道如何撰寫 astro 能看懂的 markdown 檔了 👍