gatsbyJavaScriptReact

Gatsbyの@mosch/gatsby-source-githubでGitHubリポジトリの情報を取得する

Gatsbyを使いこなすには、data-sourceプラグインをどれだけ知っている / 使えるかが鍵かなと思います。ということで、今後お世話になりそうなsource pluginをいろいろ触ってみることにしました。 今回 […]

広告ここから
広告ここまで

Gatsbyを使いこなすには、data-sourceプラグインをどれだけ知っている / 使えるかが鍵かなと思います。ということで、今後お世話になりそうなsource pluginをいろいろ触ってみることにしました。

今回はGitHubリポジトリのデータを取得する@mosch/gatsby-source-githubです。

gatsby-source-github-repoも試そうとしたのですが、こちらはnpmから消えている様子です。

install

いつも通りnpmから落としてきましょう。

$ yarn add gatsby-source-github-repo

gatsby-config.jsで取得するリポジトリを指定

リポジトリの指定はconfig側で行います。

    {
      resolve: `@mosch/gatsby-source-github`,
      options: {           
        repository: "react-sel",
        tree: true,
        releases: true,
        user: "hideokamoto",
      }
    }

ドキュメントにはtokenの記載がありますが、なくてもpublicリポジトリはいけるみたいです。

おそらくprivateリポジトリへのアクセスやAPIのスロットリング対策で必要なのではないかと思います。

GraphQLクエリをつくる

yarn developでGraphiQLを開いてクエリを作りましょう。このプラグインでは、「GitHubリポジトリのファイルを取得できるGitHubFiles」と「GitHubリポジトリで作成したRelease情報を取得できるGithubRelease」の2種類があります。

Markdownファイル系のみ取得するクエリのサンプル

query LIST_MARKDOWN_FILES {
   allGithubFile(filter: {path: {regex: "/.md$/"}}) {
     edges {
       node {
         repository
         content
         path
       }
     }
   }
 }

Release情報を取得するクエリのサンプル

query LIST_GH_RELEASES {
   allGithubRelease {
     edges {
       node {
         id
         name
         prerelease
         htmlUrl
         publishedAt
         body
         zipballUrl
       }
     }
   }
 }

Reactで表示する

Markdownファイルを表示するコンポーネントサンプル

unified / remark-parse / remark-reactを追加して、Markdownファイルの内容をそのまま描画したコンポーネントです。

import * as React from 'react'
import {useStaticQuery, graphql, Link }  from 'gatsby'
import * as unified from 'unified'
import * as parse from 'remark-parse'
const remark2react = require('remark-react')

type AllGithubFileQuery = {
    allGithubFile: {
        edges: {
            node: {
                repository: string;
                content: string;
                path: string;
            }
        }[]
    }
}
const useAllGithubFile = () => {
    const {
        allGithubFile: {
            edges
        }
    } = useStaticQuery<AllGithubFileQuery>(graphql`query LIST_MARKDOWN_FILES {
        allGithubFile(filter: {path: {regex: "/.md$/"}}) {
          edges {
            node {
              repository
              content
              path
            }
          }
        }
      }`)
    return edges
}

export const ListGitHubDocumentFiles: React.FC = () => {
    const edges = useAllGithubFile()
    return (
        <>
            <h1>Documents</h1>
            <dl>
                {edges.map(({node}) => (
                    <React.Fragment key={node.path}>
                        <dt>{node.path}</dt>
                        <dd>
                        {
                            unified()
                                .use(parse)
                                .use(remark2react)
                                .processSync(node.content)
                                .result
                        }
                        </dd>
                    </React.Fragment>
                ))}
            </dl>
        </>
    )
}

描画するとこのようになります。

実際に使う場合は、githubFileクエリの方で個別にuseStaticQueryする形の方が現実的かもしれません。

Releaseを表示するコンポーネントサンプル

続いてReleaseを表示するサンプルです。

import * as React from 'react'
import {useStaticQuery, graphql, Link }  from 'gatsby'
import * as unified from 'unified'
import * as parse from 'remark-parse'
const remark2react = require('remark-react')

type AllGithubReleaseQuery = {
    allGithubRelease: {
        edges: {
            node: {
                id: string;
                name: string;
                prerelease: boolean;
                htmlUrl: string;
                publishedAt: string;
                body: string;
                zipballUrl: string;
            }
        }[]
    }
}
const useAllGithubRelease = () => {
    const {
        allGithubRelease: {
            edges
        }
    } = useStaticQuery<AllGithubReleaseQuery>(graphql`query LIST_RELEASES {
        allGithubRelease {
            edges {
                node {
                    id
                    name
                    prerelease
                    htmlUrl
                    publishedAt
                    body
                    zipballUrl
                }
            }
        }
      }`)
    return edges
}

export const ListGitHubReleases: React.FC = () => {
    const edges = useAllGithubRelease()
    return (
        <>
            <h1>Releases</h1>
            <pre><code>{JSON.stringify(edges,null,2)}</code></pre>
            <ul>
                {edges.map(({node}) => (
                    <li key={node.id}>
                        <h2>{node.name}</h2>
                        <dl>
                            <dt>Published at</dt>
                            <dd>{new Date(node.publishedAt).toLocaleDateString()}</dd>
                            <dt>Download</dt>
                            <dd><a href={node.zipballUrl}>ZIP file</a></dd>
                        </dl>
                        {
                            unified()
                                .use(parse)
                                .use(remark2react)
                                .processSync(node.body)
                                .result
                        }
                    </li>
                ))}
            </ul>
        </>
    )
}

zipballUrlのURLにそのままアクセスすると、ZIPファイルのダウンロードができますので、配布等にも使えそうです。

使い所

これもGitHubで公開・配布している系のツールサイトに使えそうです。

ReadmeやChangelogなどのMarkdownで書かれがちなファイルの表示方法が以下の2パターン考えられます。

  1. allGihubFilesクエリのregexでまとめて取得し、gatsby-node.jsで動的にページ生成
  2. githubFilesクエリで表示したいファイルを個別指定し、pagesにファイル配置 + useStaticQueryで表示

GitHub Actionsなどで、Releaseをpublishした際にNetlify / Vercel / AWS Amplify Consoleなどのビルドを実行させるように設定することで、ある程度GitHub側の更新にも自動で追従させられるのではないかと思います。

ブックマークや限定記事(予定)など

WP Kyotoサポーター募集中

WordPressやフロントエンドアプリのホスティング、Algolia・AWSなどのサービス利用料を支援する「WP Kyotoサポーター」を募集しています。
月額または年額の有料プランを契約すると、ブックマーク機能などのサポーター限定機能がご利用いただけます。

14日間のトライアルも用意しておりますので、「このサイトよく見るな」という方はぜひご検討ください。

広告ここから
広告ここまで

Related Category posts