Astro + Markdocで、マークダウンファイルを取り込む

Astro2.1から追加された、Markdocインテグレーションを試してみました。 A new experimental Markdoc integration has also been published along […]

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

目次

    Astro2.1から追加された、Markdocインテグレーションを試してみました。

    A new experimental Markdoc integration has also been published alongside Astro 2.1.
    https://astro.build/blog/astro-210/#markdoc-integration

    Astroプロジェクトをセットアップ

    まずはプロジェクトを立ち上げましょう。

    % npm create astro@latest
    Need to install the following packages:
      create-astro@latest
    Ok to proceed? (y) 

    対話形式でセットアップします。

       dir   Where should we create your new project?
             ./astro-markdoc
    
      tmpl   How would you like to start your new project?
             ○ Include sample files 
             ● Use blog template 
             ○ Empty
    
      deps   Install dependencies?
             Yes
    
        ts   Do you plan to write TypeScript?
             ● Yes  ○ No 
    
       use   How strict should TypeScript be?
             ● Strict (recommended)
             ○ Strictest 
             ○ Relaxed 
    
       git   Initialize a new git repository? (optional)
             ● Yes  ○ No 

    Markdocを追加する

    astroコマンドで、Markdocを追加しましょう。

    @astrojs/markdocがインストールされます。

    % npx astro add markdoc
    ✔ Resolving packages...
    
      Astro will run the following command:
      If you skip this step, you can always run it yourself later
    
     ╭────────────────────────────╮
     │ yarn add @astrojs/markdoc  │
     ╰────────────────────────────╯
    
    ✔ Continue? … yes

    Configファイルの変更も、CLIに任せることができます。

    
      Astro will make the following changes to your config file:
    
     ╭ astro.config.mjs ──────────────────────────────╮
     │ import { defineConfig } from 'astro/config';   │
     │ import mdx from '@astrojs/mdx';                │
     │ import sitemap from '@astrojs/sitemap';        │
     │                                                │
     │ import markdoc from "@astrojs/markdoc";        │
     │                                                │
     │ // https://astro.build/config                  │
     │ export default defineConfig({                  │
     │   site: 'https://example.com',                 │
     │   integrations: [mdx(), sitemap(), markdoc()]  │
     │ });                                            │
     ╰────────────────────────────────────────────────╯
    
    ? Continue? › (Y/n)

    次のメッセージが表示されれば完了です。

    ───────────────────────────╯
    
    ✔ Continue? … yes
      
       success  Added the following integration to your project:
      - @astrojs/markdoc

    Markdocでコンテンツを追加しよう

    早速コンテンツを追加しましょう。

    まずはディレクトリとファイルを配置します。

    % mkdir src/content/docs
    % touch src/content/docs/hello-world.mdoc

    Markdoc公式サイトのサンプルを、hello-world.mdocに追加しました。

    ---
    title: What is Markdoc?
    ---
    
    # {% $markdoc.frontmatter.title %} {% #overview %}
    
    Markdoc is a Markdown-based syntax and toolchain for creating custom documentation sites. Stripe created Markdoc to power [our public docs](http://stripe.com/docs).
    
    {% callout type="check" %}
    Markdoc is open-source—check out its [source](http://github.com/markdoc/markdoc) to see how it works.
    {% /callout %}
    
    ## How is Markdoc different?
    
    Markdoc uses a fully declarative approach to composition and flow control, where other solutions… [Read more](/docs/overview).
    
    ## Next steps
    - [Install Markdoc](/docs/getting-started)
    - [Explore the syntax](/docs/syntax)

    {% $markdoc.frontmatter.title %}など、Markdoc独自の構文が含まれています。

    今回のようなデモ・試してみた系には、ちょうどよさそうです。

    Astrodえページを生成する

    作成したファイルを元に、ページを生成しましょう。

    まずはディレクトリとファイルを作成します。

    % mkdir src/pages/docs 
    % touch "src/pages/docs/[...slug].astro"

    src/pages/docs/[...slug].astroにコンテンツの中身を表示するコードを追加します。

    ---
    import { CollectionEntry, getCollection } from 'astro:content';
    
    export async function getStaticPaths() {
        const posts = await getCollection('docs');
        return posts.map((post) => ({
            params: { slug: post.slug },
            props: post,
        }));
    }
    type Props = CollectionEntry<'docs'>;
    
    const post = Astro.props;
    const { Content } = await post.render();
    ---
    
    <h1>{post.data.title}</h1>
    <Content />

    getStaticPathsで、getCollection('ディレクトリ名')からページに生成します。

    この辺りは、Markdownやmdxを使う際とほぼ同じではないかと思います。

    ローカルで動かしてみる

    astro devを実行すると、mdocに記載した内容が描画されます。

    Markdocでタグをカスタマイズする

    ここまでだと、普通のMarkdownと変わり映えしないので、タグをカスタマイズしてみます。

    src/components/Heading.astroを作成して、コードを追加しましょう。

    <header id={Astro.props.id}>
        <h1 class={`level-${Astro.props.level}`}><slot></slot></h1>
    </header>

    astro.config.mjsで作成したタグとカスタマイズするMarkdocタグを関連づけます。

    export default defineConfig({
      site: 'https://example.com',
      integrations: [mdx(), sitemap(), markdoc({
        nodes: {
          heading: {
            render: 'Heading',
            attributes: {
              level: {
                type: String
              }
            }
          }
        }
      })]
    });

    最後に、src/pages/docs/[...slug].astroでタグを読み込ませましょう。

    ---
    import { CollectionEntry, getCollection } from 'astro:content';
    import Heading from '../../components/Heading.astro'
    
    export async function getStaticPaths() {
        const posts = await getCollection('docs');
        return posts.map((post) => ({
            params: { slug: post.slug },
            props: post,
        }));
    }
    type Props = CollectionEntry<'docs'>;
    
    const post = Astro.props;
    const { Content } = await post.render();
    ---
    
    <h1>{post.data.title}</h1>
    <Content
        components={{ Heading }}
    />

    これでカスタマイズできます。

    独自タグや既存のMarkdown構文のカスタマイズに、活用しましょう。

    おまけ: Cloudflare Pagesへデプロイ

    Cloudflare Pagesにデプロイしてみましょう。

    SSGとしてデプロイするため、Astroでビルドしてからデプロイします。

    % npm run build
    % npx wrangler pages publish dist

    新しいプロジェクトの作成や、既存プロジェクトへの連携が行えます。

    
    No project selected. Would you like to create one or use an existing project?
    ❯ Create a new project
      Use an existing project
    ? Enter the name of your new project: › astro-markdoc
    ✔ Enter the production branch name: … main

    デプロイが始まります。

    
    POST /pages/assets/upload
    POST /pages/assets/upload
    POST /pages/assets/upload
    result: null
    result: null
    result: null
    🌍  Uploading... (20/20)
    
    ✨ Success! Uploaded 20 files (2.80 sec)
    
    ✨ Deployment complete! Take a peek over at https://xxxxx.astro-markdoc.pages.dev

    アップロードできました。

    これでAstroとMarkdocを利用したサイトを、Cloudflare Pagesでホストできます。

    Markdownなどのファイル読み込み系は、SSR難しそうかも

    AstroのSSRモードも、Cloudflare Pages(Workers)で試してみました。

    次のようなエラーが出たため、現在はSSGでの利用が良いかもしれません。

     error   post.render is not a function
      File:
        /Users/sandbox/astro-markdoc/src/pages/docs/[...slug].astro:23:34
      Stacktrace:
    TypeError: post.render is not a function
        at eval (/Users/sandbox/astro-markdoc/src/pages/docs/[...slug].astro:23:34)

     error   Could not resolve "module"
      File:
        dist/$server_build/_worker.mjs:10:7
      Code:
        9 | import 'string-width';
        > 10 | import 'module';
             |       ^
          11 | import 'node:fs/promises';
          12 | import 'node:url';
          13 | import 'html-escaper';

    Markdocではなく、「ファイルを読み込む処理」がWorkersで引っかかっているのかも・・・?

    参考

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark