การเขียนโค้ดด้วย APIการแมป JS components ไปยัง (Gutenberg) blocks
การแมป JS components ไปยัง (Gutenberg) blocks
คู่มือนี้นำเสนอตัวอย่างแอป Preact ที่ queries ข้อมูล block และแมปเข้ากับ JavaScript components ที่กำหนดเอง
เพื่อรันแอป Preact ด้านล่างในรูปแบบไฟล์ .html แบบ static ในเบราว์เซอร์ Schema Configuration ที่ใช้กับ endpoint จะต้องมี Response Headers ที่มีค่าดังนี้:
Access-Control-Allow-Origin: null
Access-Control-Allow-Headers: content-type,content-length,accept(โค้ด HTML ด้านล่างได้รับแรงบันดาลใจจาก ตัวอย่าง Preact ใน Automattic/vip-block-data-api)
GraphQL query ที่อยู่ในโค้ดด้านล่างดึงข้อมูล block ของโพสต์เป็น JSON object (ผ่านฟิลด์ CustomPost.blockDataItems) จากนั้นโค้ด JavaScript จะแมปแต่ละรายการข้อมูล block ไปยัง component ที่กำหนดเอง:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gato GraphQL - Mapping JS components to (Gutenberg) blocks: Preact example</title>
</head>
<body></body>
<script type="module">
import { h, render } from 'https://esm.sh/preact';
// Input here your domain, and enable the single endpoint
const endpoint = "https://mysite.com/graphql/";
// Input here the ID of a post with blocks
const postId = 40;
renderPost(endpoint, postId);
async function renderPost(endpoint, postId) {
const data = {
query: `
query GetPost($postId: ID!) {
post(by: { id: $postId }) {
title
blockDataItems
}
}
`,
variables: {
postId: `${ postId }`
},
};
const response = await fetch(
endpoint,
{
method: 'post',
body: JSON.stringify(data),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Content-Length': data.length,
},
}
);
// Execute the query, and await the response
const json = await response.json();
// If the query produced errors, exit
if (json.errors) {
console.log(JSON.stringify(json.errors));
return;
}
// Uncomment here to visualize the GraphQL response
// console.log(json.data);
const postTitle = json.data.post?.title;
const blocks = json.data.post?.blockDataItems;
const App = Post(postTitle, blocks);
render(App, document.body);
}
function mapBlockToComponent(block) {
if (block.name === 'core/heading') {
return Heading(block);
} else if (block.name === 'core/paragraph') {
return Paragraph(block);
} else if (block.name === 'core/media-text') {
return MediaText(block);
} else if (block.name === 'core/gallery') {
return Gallery(block);
} else if (block.name === 'core/image') {
return Image(block);
} else {
return null;
}
}
/* Components */
function Post(title, blocks) {
return h('div', { className: 'post' },
h('h1', null, title),
blocks.map(mapBlockToComponent),
);
}
function Heading(props) {
// Use dangerouslySetInnerHTML for rich text formatting
return h('h2', { dangerouslySetInnerHTML: { __html: props.attributes.content } });
}
function Paragraph(props) {
// Use dangerouslySetInnerHTML for rich text formatting
return h('p', { dangerouslySetInnerHTML: { __html: props.attributes.content } });
}
function MediaText(props) {
return h('div', { className: 'media-text' },
h('div', { className: 'media' },
h('img', { src: props.attributes.mediaUrl })
),
h('div', { className: 'text' },
props.innerBlocks ? props.innerBlocks.map(mapBlockToComponent) : null,
),
)
}
function Gallery(props) {
return h('div', { className: 'gallery' },
h('div', { className: 'images' },
props.innerBlocks ? props.innerBlocks.map(mapBlockToComponent) : null,
),
)
}
function Image(props) {
return h('img', { src: props.attributes.url });
}
</script>
</html>การรันแอปพลิเคชันจะสร้างโค้ด HTML ต่อไปนี้จากข้อมูลโพสต์:
<div class="post">
<h1>Welcome to a single post full of blocks!</h1>
<p>When I look back on my past and think how much time I wasted on nothing, how much time has been lost in futilities, errors, laziness, incapacity to live; how little I appreciated it, how many times I sinned against my heart and soul-then my heart bleeds. <strong>Life is a gift, life is happiness, every minute can be an eternity of happiness</strong>. (<a href="https://www.azquotes.com/author/4085-Fyodor_Dostoevsky" target="_blank" rel="noopener">Quote by Fyodor Dostoevsky</a>)<br></p>
<h2>This blog post will be transformed...</h2>
<p>If you make it a habit not to blame others, you will feel the growth of the ability to love in your soul, and you will see the growth of goodness in your life. (<a href="https://www.azquotes.com/author/14706-Leo_Tolstoy" target="_blank" rel="noopener">Quote by Leo Tolstoy</a>)<br></p>
<img src="https://i.ytimg.com/vi/z4KKd2nGlEM/maxresdefault.jpg">
<h2><mark style="background-color:#D1D1E4" class="has-inline-color">I love these veggies!!!</mark></h2>
<h2>When going to eat out, I normally go for one of these:</h2>
<h2>This heading (H3) is boring (Regex test: $1 #1), but these guys are not</h2>
<div class="gallery">
<div class="images">
<img src="https://i.insider.com/5f44388342f43f001ddfec52">
<img src="https://i.pinimg.com/originals/85/a7/f5/85a7f5cee4c93cb3995d1b51e3a0289f.jpg">
</div>
</div>
</div>