Astroのrssフィードに記事の本文を追加する
初稿:
- 7 min read -
記事概要
- 先日のBloggerからAstroへ移行した記事の別途詳細
※参考 - Blog移行記事
10年以上の期間お世話になったGoogle Bloggerに別れを告げ、この度AstroでBlogサイトを構築し移行した。Astroは静的サイトを手軽に開発できる軽量フレームワーク。無料のテンプレートをベースにカスタマイズを行った。それなりの作業ボリュームとなったので、詳細は別記事に分け、今回は移行作業全体をまとめる。
目的
- 「@astrojs/rss」で出力するrss.xmlに、Blog記事の本文を追加する
- Blog記事の本文は、全文を出力する
- Blog記事はMDXで記述している
- RSSリーダーで読みやすい形式で出力するため以下を考慮する
- markdwon記法をパーサーでHTMLに変換する
- XSSなどセキュリティリスクを回避するためサニタイズ処理をする
- 一連の実装についてまとめる
用語説明
Astro とは?
Astroは、ブログやマーケティング、eコマースなど、コンテンツ駆動のウェブサイトを作成するためのウェブフレームワークです。Astroは、新しいフロントエンドアーキテクチャを開拓し、他のフレームワークと比較してJavaScriptのオーバーヘッドと複雑さを低減することで知られています。高速でSEOに優れたウェブサイトが必要なら、Astroが最適です。 — Astro公式Docs より引用
MDXとは?
MDXでは、マークダウン・コンテンツでJSXを使用することができます。インタラクティブなチャートやアラートなどのコンポーネントをインポートして、コンテンツに埋め込むことができます。これにより、コンポーネントを使った長文のコンテンツ作成が簡単になります。 — What is MDX? | MDXより引用
markdown-itとは?
- markdown記法のテキストをHTMLに変換するパーサー
- markdown-it/markdown-it
sanitize-htmlとは?
- XSS等の攻撃対象となりうるhtmlタグや属性をエスケープや削除する
- sanitize-html - npm
作業環境
- OS - Ubuntu-22.04LTS on WSL2
- Node.js - v20.14.0
- pnpm - v9.4.0
- Astro - v4.11.3
作業概要
- 公式Docsを参考にrss.xml.tsを作成する
- markdown-itとsanitize-htmlをインストールする
- MDX→HTML変換モジュールを作成する
- 上記モジュールをrss.xml.tsに組み込む
作業詳細
標準的なrss.xml.tsを作成する
- 公式Docのサンプルに沿って、rss.xml.tsを作成する
- 公式サンプルと異なるのは以下。
- サイト情報を自前のconfigより取得
- link生成関数
- header(Content-Type)を追加
- 加工無しの本文 post.body
markdown-itとsanitize-htmlをインストールする
- markdown-itとsanitize-htmlパッケージをプロジェクトにインストール
- TypeScriptの人は@typesも
MDX→HTML変換モジュールを作成する
ここは作業ボリュームが多いため、章に分けて記述する。
要件
- import文を削除する(frontmatter直後のみ)
- componentなどMDXに埋め込んだHTMLタグはsanitizeした上でそのまま出力する
使用モジュール
- sanitize-html
- markdown-it
処理ステップ
- sanitizeOptions定義作成
- imgタグとalt属性、ankerのhref属性を有効化
- sanitize-html - default-options
- frontmatter直下のimport文のみ削除
- コンテンツとして書かれたimport文を削除しないため
- 最初のサニタイズ処理を実行
- 本文はまだMDX形式
- ターゲットはcode blockやcomponent
- HTML特殊文字にパースされた山カッコを戻す
- ターゲットは最初のサニタイズで削除されずにHTMLパースされた箇所
- これを再度HTML化する
- textlintのignoreコメントを削除
- MDX上でtextlintの処理を避けたい箇所に使用しているもの
- markdown-itでHTMLに変換
- 最終的なサニタイズ処理を実行
サニタイズを2度行う理由
- パース→サニタイズを通常どおり行うと、MDXに埋め込まれているHTMLタグが文字列として出力される
- code blockに書かれたコードはサニタイズが必要
- 以上を考慮し、実装する方法として以下の処理ステップとした
- MDXのままサニタイズ
- HTMLのまま出力したい箇所をリバース
- markdownパース
- 最終サニタイズ
完成したモジュール
上記モジュールをrss.xml.tsに組み込む
- mdxUtils.tsのモジュールをimportする
- tsconfigでpathsを定義しているので適宜修正を
- contentにmdxToHtml関数で処理した値を設定
以上