From 1c7f4858d860c420f3d27b1cc60a7864ae952707 Mon Sep 17 00:00:00 2001 From: Shinya Fujino Date: Sat, 2 Sep 2023 17:58:43 +0900 Subject: [PATCH 1/6] i18n(ja): Add rss.mdx --- src/content/docs/ja/guides/rss.mdx | 220 +++++++++++++++++++++-------- 1 file changed, 160 insertions(+), 60 deletions(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index 1d2e707a0bbe8..a6ee6d6bc6255 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -1,19 +1,20 @@ --- -title: RSS -description: AstroのRSS入門 +title: RSSフィードの追加 +description: AstroサイトにRSSフィードを追加して、ユーザーがコンテンツを購読できるようにします。 i18nReady: true type: recipe --- import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro' +import Since from '~/components/Since.astro' -Astroはブログやその他のコンテンツウェブサイト向けに、RSSフィードの高速な自動生成をサポートしています。一般的なRSSフィードに関する情報は[aboutfeeds.com](https://aboutfeeds.com/)をご覧ください。 +Astroはブログやその他のコンテンツウェブサイト向けに、RSSフィードの高速な自動生成をサポートしています。RSSフィードにより、ユーザーはコンテンツを簡単に購読できます。 ## `@astrojs/rss`の準備 `@astrojs/rss`パッケージは、[APIエンドポイント](/ja/core-concepts/endpoints/#静的ファイルのエンドポイント)を利用したRSS生成のヘルパーを提供します。静的ビルドと[SSRアダプター](/ja/guides/server-side-rendering/#アダプターの追加)を利用したオンデマンド生成の両方に対応しています。 -はじめに、お好きなパッケージマネージャーで`@astrojs/rss`をインストールします。 +1. お好きなパッケージマネージャーで`@astrojs/rss`をインストールします。 @@ -33,91 +34,179 @@ Astroはブログやその他のコンテンツウェブサイト向けに、RSS -次に、プロジェクトの`astro.config`に[`site`を設定](/ja/reference/configuration-reference/#site)していることを確認します。これを利用して、[`SITE`環境変数経由](/ja/guides/environment-variables/#デフォルト環境変数)でRSSフィード内のリンクを生成することになります。 - -:::note[Astro v1が必要です] -`SITE`環境変数はAstro v1ベータ版でのみ利用できます。Astroの最新バージョン(`astro@latest`)にアップグレードするか、不可能な場合、手動で`site`を書いてください。(次の例を参照してください) +:::tip +プロジェクトの`astro.config`に[`site`を設定](/ja/reference/configuration-reference/#site)していることを確認してください。これはRSSフィード内のリンクを生成するために利用されます。 ::: -それでは、はじめてのRSSフィードを生成しましょう。`src/pages`ディレクトリに`rss.xml.js`を作ります。`rss.xml`は出力されるURLになりますので、必要であれば名前を変更しても構いません。 +2. 任意の名前で`src/pages/`に`.xml.js`拡張子のファイルを作成します。これはフィードの出力URLとして利用されます。一般的なRSSフィードのURL名は`feed.xml`や`rss.xml`です。 -次に、`@astrojs/rss`パッケージから`rss`ヘルパーをインポートし、次のパラメーターで呼び出します。 +以下の`src/pages/rss.xml.js`ファイルの例では、`site/rss.xml`にRSSフィードを生成します。 -```js -// src/pages/rss.xml.js +3. `@astrojs/rss`パッケージから`rss()`ヘルパーを`.xml.js`ファイルにインポートし、以下のパラメーターで`rss()`を呼び出した結果を返す関数をエクスポートします。 + +```js title="src/pages/rss.xml.js" import rss from '@astrojs/rss'; -export const get = () => rss({ - // 出力されるXMLの``フィールド - title: 'Buzz’s Blog', - // 出力されるXMLの`<description>`フィールド - description: 'A humble Astronaut’s guide to the stars', - // RSS内<item>リンクのベースURL - // SITEはプロジェクトのastro.configにあるsiteの値が使用されます。 - site: import.meta.env.SITE, - // 出力されるXMLの<item>のリスト - // 簡単な例: src/pagesにあるマークダウンファイルからそれぞれitemsを生成する - // 必要なfrontmatterや複雑なユースケースに関しては「`items`の生成」セクションをご覧ください。 - items: import.meta.glob('./**/*.md'), - // (任意) カスタムxmlを利用する - customData: `<language>en-us</language>`, -}); +export function GET(context) { + return rss({ + // 出力されるXMLの`<title>`フィールド + title: 'Buzz’s Blog', + // 出力されるXMLの`<description>`フィールド + description: 'A humble Astronaut’s guide to the stars', + // エンドポイントのコンテキストからプロジェクトの"site"を取得 + // https://docs.astro.build/ja/reference/api-reference/#contextsite + site: context.site, + // 出力されるXMLの<item>の + // コンテンツコレクションやglobインポートを利用した例については「`items`の生成」セクションをご覧ください + items: [], + // (任意) カスタムXMLを挿入 + customData: `<language>en-us</language>`, + }); +} ``` ## `items`の生成 -`items`フィールドはこのどちらかを受け付けます。 -1. [`import.meta.glob(...)`の結果](#1-importmetaglobの結果) **(`src/pages`ディレクトリに含まれる`.md`ファイルのみ利用します)** -2. [RSSフィードオブジェクトのリスト](#2-rssフィードオブジェクトのリスト)。各オブジェクトは`link`, `title`, `pubDate`、オプションで`description`, `customData`フィールドを持ちます。 +`items`フィールドは、RSSフィードのオブジェクトのリストを受け入れます。各オブジェクトには、`link`、`title`、`pubDate`の3つの必須フィールドがあります。`description`(短い抜粋)、`content`(記事の全文)、ブログ記事の他のフロントマタープロパティなど追加のデータのための`customData`フィールド、という3つの値も任意で含められます。 -### 1. `import.meta.glob`の結果 +コンテンツコレクションのスキーマからや、`src/pages/`内のブログ記事に対して[globインポート](/ja/guides/imports/#astroglob)を利用することで、この配列を生成できます。 -`src/pages`にある`.md`ファイルの便利な簡易記法としておすすめの選択肢です。各投稿のfrontmatterに`title`と`pubDate`、任意で`description`と`customData`フィールドを持たせてください。これが不可能な場合やコードでfrontmatterを生成したい場合は[2の選択肢](#2-rssフィードオブジェクトのリスト)をご覧ください。 -ブログ投稿を`src/pages/blog`ディレクトリに保存しているとしましょう。次のようにRSSフィードを生成できます。 +### コンテンツコレクションを使う -```js -// src/pages/rss.xml.js +[コンテンツコレクション](/ja/guides/content-collections/)で管理されているページのRSSフィードを作成するには、`getCollection()`関数を利用してアイテムのリストを取得します。 + + +```js title="src/pages/rss.xml.js" "items:" "const blog = await getCollection('blog');" import rss from '@astrojs/rss'; +import { getCollection } from 'astro:content'; + +export async function GET(context) { + const blog = await getCollection('blog'); + return rss({ + title: 'Buzz’s Blog', + description: 'A humble Astronaut’s guide to the stars', + site: context.site, + items: blog.map((post) => ({ + title: post.data.title, + pubDate: post.data.pubDate, + description: post.data.description, + customData: post.data.customData, + // 記事の`slug`からRSSリンクを生成 + // この例では、すべての記事が`/blog/[slug]`ルートでレンダリングされていると仮定しています + link: `/blog/${post.slug}/`, + })), + }); +} +``` + +任意: 期待されるRSSプロパティを強制するために、既存のブログコレクションスキーマを置き換えます。 -export const get = () => rss({ - title: 'Buzz’s Blog', - description: 'A humble Astronaut’s guide to the stars', - site: import.meta.env.SITE, - items: import.meta.glob('./blog/**/*.md'), +すべてのブログエントリが有効なRSSフィードアイテムを生成することを保証するために、スキーマの個別のプロパティを定義する代わりに、`rssSchema`をインポートして適用できます。 + +```js title="src/content/config.ts" "rssSchema" +import { defineCollection } from 'astro:content'; +import { rssSchema } from '@astrojs/rss'; + +const blog = defineCollection({ + schema: rssSchema, }); + +export const collections = { blog }; ``` -このインポートの構文は[Viteのglob importのドキュメント](https://vitejs.dev/guide/features.html#glob-import)を参照してください。 +### globインポートを使う + +<Since v="2.1.0" pkg="@astrojs/rss" /> -### 2. RSSフィードオブジェクトのリスト +`src/pages/`内のドキュメントからRSSフィードを作成するには、`pagesGlobToRssItems()`ヘルパーを利用します。これは[`import.meta.glob`](https://vitejs.dev/guide/features.html#glob-import)の結果を入力とし、有効なRSSフィードアイテムの配列を出力します(含めるページを指定するためのglobパターンの書き方については[こちら](/ja/guides/imports/#globパターン)を確認してください)。 -`pages`ディレクトリの外にある`.md`ファイルにおすすめな選択肢です。[`getStaticPaths`で](/ja/reference/api-reference/#getstaticpaths)ルーティングを生成する場合によく使います。 +:::caution +この関数は、必要なフィードプロパティが各ドキュメントのフロントマターに存在することを前提としていますが、その検証はおこないません。エラーが発生した場合は、各ページのフロントマターを手動で確認してください。 +::: -たとえば`src/posts`ディレクトリに`.md`投稿を保存しているとします。各投稿は`title`, `pubDate`と`slug`をfrontmatterに持ち、`slug`はサイト上の出力されるURLに対応しています。[Viteの`import.meta.glob`ヘルパー](https://vitejs.dev/guide/features.html#glob-import)を使って、次のようにRSSフィードを生成できます。 +```js title="src/pages/rss.xml.js" "pagesGlobToRssItems" "await pagesGlobToRssItems(" +import rss, { pagesGlobToRssItems } from '@astrojs/rss'; + +export async function GET(context) { + return rss({ + title: 'Buzz’s Blog', + description: 'A humble Astronaut’s guide to the stars', + site: context.site, + items: await pagesGlobToRssItems( + import.meta.glob('./blog/*.{md,mdx}'), + ), + }); +} +``` +:::note[古いバージョンを利用していますか?] +v2.1.0より前のバージョンの`@astrojs/rss`では、`pagesGlobToRssItems()`ラッパーなしでグロブ結果を`items`にそのまま渡します。 ```js -// src/pages/rss.xml.js +items: import.meta.glob('./blog/*.{md,mdx}'), +``` +::: + +### 記事の全文を含める + +<Since v="1.6.14" /> + +`content`キーには、記事の全文をHTMLとして含めます。これにより、RSSフィードリーダーは記事全文を利用できるようになります。 + +:::tip +[`sanitize-html`](https://www.npmjs.com/package/sanitize-html)などのパッケージを利用すると、コンテンツが適切にサニタイズ、エスケープ、エンコードされることを保証できます。 +::: + +コンテンツコレクションを利用する場合は、[`markdown-it`](https://github.com/markdown-it/markdown-it)などの標準的なMarkdownパーサーを利用して記事の`body`をレンダリングし、その結果をサニタイズします。 + +```js title="src/pages/rss.xml.js" ins={3, 4, 5, 16} import rss from '@astrojs/rss'; +import { getCollection } from 'astro:content'; +import sanitizeHtml from 'sanitize-html'; +import MarkdownIt from 'markdown-it'; +const parser = new MarkdownIt(); + +export async function GET(context) { + const blog = await getCollection('blog'); + return rss({ + title: 'Buzz’s Blog', + description: 'A humble Astronaut’s guide to the stars', + site: context.site, + items: blog.map((post) => ({ + link: `/blog/${post.slug}/`, + // 注: MDXファイルのコンポーネントやJSX式は処理されません。 + content: sanitizeHtml(parser.render(post.body)), + ...post.data, + })), + }); +} +``` -const postImportResult = import.meta.glob('../posts/**/*.md', { eager: true }); -const posts = Object.values(postImportResult); - -export const get = () => rss({ - title: 'Buzz’s Blog', - description: 'A humble Astronaut’s guide to the stars', - site: import.meta.env.SITE, - items: posts.map((post) => ({ - link: post.url, - title: post.frontmatter.title, - pubDate: post.frontmatter.pubDate, - })) -}); +Markdownでglobインポートを利用する場合は、`compiledContent()`ヘルパーを利用してレンダリングされたHTMLを取得しサニタイズできます。この機能はMDXファイルでは**サポートされていない**ことに注意してください。 + +```js title="src/pages/rss.xml.js" ins={2, 13} +import rss from '@astrojs/rss'; +import sanitizeHtml from 'sanitize-html'; + +export function GET(context) { + const postImportResult = import.meta.glob('../posts/**/*.md', { eager: true }); + const posts = Object.values(postImportResult); + return rss({ + title: 'Buzz’s Blog', + description: 'A humble Astronaut’s guide to the stars', + site: context.site, + items: posts.map((post) => ({ + link: post.url, + content: sanitizeHtml(post.compiledContent()), + ...post.frontmatter, + })), + }); +} ``` ## スタイルシートの追加 -ブラウザでファイルを見たときのユーザー体験をよくするために、RSSフィードにスタイルを加えられます。 +ブラウザでファイルを見たときのユーザー体験をよくするために、RSSフィードにスタイルを追加しましょう。 `rss`関数の`stylesheet`オプションにスタイルシートの絶対パスを指定してください。 @@ -129,4 +218,15 @@ rss({ }); ``` -RSSのスタイルシートを特に気にしない場合、[Pretty Feed v3 default stylesheet](https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl)がおすすめです。これはGitHubからダウンロードでき、プロジェクトの`public`ディレクトリに保存します。 +:::tip +スタイルシートを自分で作成したくない場合は、[Pretty Feed v3のデフォルトスタイルシート](https://github.com/genmon/aboutfeeds/blob/main/tools/pretty-feed-v3.xsl)などの既製のスタイルシートも利用できます。GitHubからスタイルシートをダウンロードし、プロジェクトの`public/`ディレクトリに保存してください。 +::: + +## 次のステップ + +ブラウザにより`your-domain.com/rss.xml`のフィードにアクセスし、各記事のデータが表示されることを確認できたら、[サイトでフィードを宣伝](https://medium.com/samsung-internet-dev/add-rss-feeds-to-your-website-to-keep-your-core-readers-engaged-3179dca9c91e#:~:text=com/~deno%2Drss-,Advertising%20your%20RSS%20feed,-Now%20you%20have)してみましょう。サイトに標準のRSSアイコンを追加すると、読者は自分のフィードリーダーであなたの記事を購読できることに気付けます。 + + +## 参考 + +- [RSSフィードについて](https://aboutfeeds.com/) From c532396185a38b89ae3f445fd0f1ef156a7fad04 Mon Sep 17 00:00:00 2001 From: Shinya Fujino <shf0811@gmail.com> Date: Sun, 3 Sep 2023 12:47:58 +0900 Subject: [PATCH 2/6] Update src/content/docs/ja/guides/rss.mdx Co-authored-by: Kyosuke Nakamura <kyosuke@users.noreply.github.com> --- src/content/docs/ja/guides/rss.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index a6ee6d6bc6255..e5eaeae4b537a 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -72,7 +72,7 @@ export function GET(context) { コンテンツコレクションのスキーマからや、`src/pages/`内のブログ記事に対して[globインポート](/ja/guides/imports/#astroglob)を利用することで、この配列を生成できます。 -### コンテンツコレクションを使う +### コンテンツコレクションの使用 [コンテンツコレクション](/ja/guides/content-collections/)で管理されているページのRSSフィードを作成するには、`getCollection()`関数を利用してアイテムのリストを取得します。 From dba22da9ac4e9d5aeae07363d988aba10f3571ca Mon Sep 17 00:00:00 2001 From: Shinya Fujino <shf0811@gmail.com> Date: Sun, 3 Sep 2023 12:48:48 +0900 Subject: [PATCH 3/6] Update src/content/docs/ja/guides/rss.mdx Co-authored-by: Kyosuke Nakamura <kyosuke@users.noreply.github.com> --- src/content/docs/ja/guides/rss.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index e5eaeae4b537a..432ac3a86b657 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -100,7 +100,7 @@ export async function GET(context) { } ``` -任意: 期待されるRSSプロパティを強制するために、既存のブログコレクションスキーマを置き換えます。 + オプション:期待されるRSSプロパティを強制するために、既存のブログコレクションスキーマを置き換えます。 すべてのブログエントリが有効なRSSフィードアイテムを生成することを保証するために、スキーマの個別のプロパティを定義する代わりに、`rssSchema`をインポートして適用できます。 From 0dfe611723331d11b1d0542145ef1bdcd481a25b Mon Sep 17 00:00:00 2001 From: Shinya Fujino <shf0811@gmail.com> Date: Sun, 3 Sep 2023 12:48:55 +0900 Subject: [PATCH 4/6] Update src/content/docs/ja/guides/rss.mdx Co-authored-by: Kyosuke Nakamura <kyosuke@users.noreply.github.com> --- src/content/docs/ja/guides/rss.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index 432ac3a86b657..9fb7070fc7bfe 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -115,7 +115,7 @@ const blog = defineCollection({ export const collections = { blog }; ``` -### globインポートを使う +### globインポートの使用 <Since v="2.1.0" pkg="@astrojs/rss" /> From 46ded777bbdc5edce7e88540990fed8b6356f493 Mon Sep 17 00:00:00 2001 From: Shinya Fujino <shf0811@gmail.com> Date: Sun, 3 Sep 2023 12:49:27 +0900 Subject: [PATCH 5/6] Update src/content/docs/ja/guides/rss.mdx Co-authored-by: Kyosuke Nakamura <kyosuke@users.noreply.github.com> --- src/content/docs/ja/guides/rss.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index 9fb7070fc7bfe..7a5a70a48e674 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -119,7 +119,7 @@ export const collections = { blog }; <Since v="2.1.0" pkg="@astrojs/rss" /> -`src/pages/`内のドキュメントからRSSフィードを作成するには、`pagesGlobToRssItems()`ヘルパーを利用します。これは[`import.meta.glob`](https://vitejs.dev/guide/features.html#glob-import)の結果を入力とし、有効なRSSフィードアイテムの配列を出力します(含めるページを指定するためのglobパターンの書き方については[こちら](/ja/guides/imports/#globパターン)を確認してください)。 +`src/pages/`内のドキュメントからRSSフィードを作成するには、`pagesGlobToRssItems()`ヘルパーを利用します。これは[`import.meta.glob`](https://vitejs.dev/guide/features.html#glob-import)の結果を入力とし、有効なRSSフィードアイテムの配列を出力します(含めるページを指定するためには、[globパターンの書き方について](/ja/guides/imports/#globパターン)を確認してください)。 :::caution この関数は、必要なフィードプロパティが各ドキュメントのフロントマターに存在することを前提としていますが、その検証はおこないません。エラーが発生した場合は、各ページのフロントマターを手動で確認してください。 From 8bfead2e18f34d4107f8edafe382ab9ada8db8bb Mon Sep 17 00:00:00 2001 From: Shinya Fujino <shf0811@gmail.com> Date: Sun, 3 Sep 2023 12:49:34 +0900 Subject: [PATCH 6/6] Update src/content/docs/ja/guides/rss.mdx Co-authored-by: Kyosuke Nakamura <kyosuke@users.noreply.github.com> --- src/content/docs/ja/guides/rss.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/ja/guides/rss.mdx b/src/content/docs/ja/guides/rss.mdx index 7a5a70a48e674..9996a548b4529 100644 --- a/src/content/docs/ja/guides/rss.mdx +++ b/src/content/docs/ja/guides/rss.mdx @@ -141,7 +141,7 @@ export async function GET(context) { ``` :::note[古いバージョンを利用していますか?] -v2.1.0より前のバージョンの`@astrojs/rss`では、`pagesGlobToRssItems()`ラッパーなしでグロブ結果を`items`にそのまま渡します。 +v2.1.0より前のバージョンの`@astrojs/rss`では、`pagesGlobToRssItems()`ラッパーなしでglob結果を`items`にそのまま渡します。 ```js items: import.meta.glob('./blog/*.{md,mdx}'), ```