Remark Transformer Pluginを作ってみる 日本語ではあまり書かれているのがないが、英語でも翻訳にかけたらわかりやすかったのでそのままやってみる。 www.gatsbyjs.com
マークダウンのAST木についての理解 マークダウン→AST→HTMLという風に変換するのを途中の処理に割り込んで機能を付加する方法を見ていく。
実際の作業
- pluginsというフォルダーを作る
- フォルダー内でnpm initしてpackage.jsonを作る
npm initすると色々聞かれるが、わからなかったらauthorやpackage名ぐらいの入力であとはエンターでいいと思う。gatsby-remark-amazon-jsonというのを作ってみて、gatsby-transformer-remarkのプラグインとして追加する。gatsby-starter-blogを使っているので初期からgatsby-remark-images、gatsby-remark-responsive-iframe、gatsby-remark-prismjsが入っているので追加する形になる。プラグインの記述される順序が処理の順番になるので重要。
{
resolve: `gatsby-transformer-remark`,
options: {
plugins: [`gatsby-remark-amazon-json`],
},
},
マークダウンのプラグインを作るのにunist-util-visitを使うのが一般的らしい。ただ最新のバージョンだとgatsbyで動かないとか。
注意:新しいメジャーバージョンはESMであり、ギャツビーはまだ完全にサポートしていないため、unist-util-visitのv2をインストールしています。
npm install unist-util-visit
npm install unist-util-visit@^2
ver.5を入れると書きエラーが出た
import {visit} from 'unist-util-visit' ^^^^^^ SyntaxError: Cannot use import statement outside a module
markdownのプラグインを作るほうで考えていたが、独自コンポーネントでいいような気がした。 いっそのことmdじゃなくてmdxにすればもっと簡単かも。 コンポーネントをpropsで渡すと配列でも行ける。受け取ったasinをgraphqlで検索して描画する。
// src/pages/page3.js
import React from "react"
import Amazon from "../components/Amazon"
export default function Page3() {
const books=["B086L8S2CV","B0B683NKKV"]
return (
<div>
<Amazon asin={books} />
<Amazon asin="B07N8ZT86X" />
</div>
)
}
import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
const Amazon = ({ asin }) ={
const data = useStaticQuery(graphql`
query MyQuery {
allJson {
edges {
node {
Asin
Booktype
Category
Contributor
ImageURL
Points
Price
Publisher
Title
URL
}
}
}
}
`)
const book = data.allJson.edges
//const asin=["B08DTXKTFV","B0B683NKKV"]
var file = book.filter(word =asin.includes(word.node.Asin));
console.log(book)
return (
<div>
{file.map(e =(
<div key={e.node.Asin}>
<a className="amazon-card-container" href={e.node.URL}>
<div className="amazon-card-body">
<div className="amazon-card-title">{e.node.Title}</div>
<div className="amazon-card-domain">{e.node.Contributor}、出版社:{e.node.Publisher}</div>
</div>
<div className="amazon-card-image-container">
<img className="amazon-card-image" src={e.node.ImageURL} loading="lazy" alt={e.node.Title}/>
</div>
</a>
</div>
))}
</div>
)
}
export default Amazon