古騰堡是 WordPress 的預設編輯器。該編輯器讓您可以通過拖放介面,使用文字、圖片、視訊和其他網站元素的離散區塊來製作和風格化內容。這種方法增強了 WordPress 的靈活性和設計能力。
本指南介紹如何在 Next.js 靜態網站中使用 WordPress REST API 將 Gutenberg 內容解析為 HTML。
前提條件
要跟上進度,您需要:
使用 REST API 獲取 Gutenberg 內容
要以程式設計方式與 WordPress 網站互動並檢索 Gutenberg 區塊中的內容結構,您可以使用 WordPress REST API 或 WPGraphQL 外掛。通過這些工具,您可以獲取 JSON 格式的 WordPress 內容。
要通過 REST API 啟用 JSON 資料訪問,請將 WordPress 的固定連結設定從 “樸素” 調整為其他形式。這樣就可以通過結構化 URL 訪問 API,如下所示:
https://yoursite.com/wp-json/wp/v2
通過向該 URL 傳送 API 請求,您可以在 WordPress 網站上以程式設計方式檢索各種資訊並執行操作。例如,您可以通過向以下網址傳送 GET 請求來獲取文章列表:
https://yoursite.com/wp-json/wp/v2/posts
這將返回一個 JSON 物件,其中包含 WordPress 網站上的文章資訊,包括標題、內容、作者詳細資訊等。
將古騰堡區塊解析為 HTML
從使用 Gutenberg 編輯器的 WordPress 網站檢索文章時,資料庫中儲存的內容會混合使用 HTML 和 JSON 後設資料來描述各種區塊型別,例如引語和相簿。例如:
<!-- wp:quote {"className":"inspirational-quote","style":{"typography":{"fontSize":"large"}}} --> <blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote> <!-- /wp:quote --> <!-- wp:gallery {"ids":[34,35],"columns":2,"linkTo":"none","sizeSlug":"medium","className":"custom-gallery"} --> <ul class="wp-block-gallery columns-2 is-cropped custom-gallery"><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34"/></figure></li><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35"/></figure></li></ul> <!-- /wp:gallery -->
該程式碼段展示了兩個 Gutenberg 區塊:引言和相簿。每個區塊都有封裝在 HTML 註釋中的 JSON 後設資料。後設資料定義了類名、樣式等屬性,以及與區塊展示相關的其他配置。
當您通過 WordPress REST API 或 WPGraphQL 獲取這些區塊時,WordPress 會對其進行處理,將 HTML 和 JSON 後設資料的組合轉換為完全呈現的 HTML 元素,您可以直接將其整合到網頁中。上述區塊轉換後的 HTML 顯示如下:
<blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote> <ul class="wp-block-gallery columns-2 is-cropped custom-gallery"> <li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34" sizes="(max-width: 300px) 100vw, 300px" /></figure></li> <li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35" sizes="(max-width: 300px) 100vw, 300px" /></figure></li> </ul>
對於使用 Next.js 等 JavaScript 框架構建解耦或無頭應用程式的開發人員來說,這提供了一種直接顯示內容的方法,即使用 dangerouslySetInnerHTML
屬性將 HTML 直接注入頁面以渲染標記。
<div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />
此外,您可能還需要對連結等元素執行進一步格式化,並處理多餘的換行符 ( \n
),本指南稍後將對此進行說明。
將 Gutenberg 區塊內容解析到 Next.js 靜態網站中
在本節中,讓我們將 WordPress 內容提取到 Next.js 專案中,然後將 Gutenberg 區塊解析為 HTML。
- 首先,設定一個從 WordPress 網站獲取文章的函式。開啟專案中的 src/page.js 檔案,用以下程式碼段替換其內容:
const getWpPosts = async () => {const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts');const posts = await res.json();return posts;};const getWpPosts = async () => { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts; };
const getWpPosts = async () => { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts; };
此非同步函式向 WordPress REST API 執行 API 請求。它會獲取網站上的所有文章,並以陣列形式返回。
- 接下來,讓我們在一個簡單的 Next.js 頁面元件中利用獲取的文章,將文章記錄到控制檯並呈現一個基本的問候語:
const page = async () => {const posts = await getWpPosts();console.log(posts);return (<div><h1>Hello World</h1></div>);};export default page;const page = async () => { const posts = await getWpPosts(); console.log(posts); return ( <div> <h1>Hello World</h1> </div> ); }; export default page;
const page = async () => { const posts = await getWpPosts(); console.log(posts); return ( <div> <h1>Hello World</h1> </div> ); }; export default page;
使用
npm run dev
執行專案時,它會顯示 “Hello World” 資訊,並將獲取的文章記錄到終端。[{"_links" : {"about" : [...],"author" : [...],"collection" : [...],"curies" : [...],"predecessor-version" : [...],"replies" : [...],"self" : [...],"version-history" : [...],"wp:attachment" : [...],"wp:term" : [...]},"author" : 1,"categories" : [...],"comment_status" : "open","content" : {"protected" : false,"rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n"},"date" : "2024-02-27T12:08:30","date_gmt" : "2024-02-27T12:08:30","excerpt" : {"protected" : false,"rendered" : "<p>Fire, a primal force, captivates with its flickering flames, evoking both awe and caution. Its dance symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate. In ancient times, fire was a beacon of light and warmth, […]</p>\n"},"featured_media" : 0,"format" : "standard","guid" : {"rendered" : "https://yoursite.com/?p=13"},"id" : 13,"link" : "https://yoursite.com/?p=13","meta" : {"footnotes" : ""},"modified" : "2024-02-29T16:45:36","modified_gmt" : "2024-02-29T16:45:36","ping_status" : "open","slug" : "fire-fire","status" : "publish","sticky" : false,"tags" : [],"template" : "","title" : {"rendered" : "Fire"},"type" : "post"},},...][ { "_links" : { "about" : [...], "author" : [...], "collection" : [...], "curies" : [...], "predecessor-version" : [...], "replies" : [...], "self" : [...], "version-history" : [...], "wp:attachment" : [...], "wp:term" : [...] }, "author" : 1, "categories" : [...], "comment_status" : "open", "content" : { "protected" : false, "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, "date" : "2024-02-27T12:08:30", "date_gmt" : "2024-02-27T12:08:30", "excerpt" : { "protected" : false, "rendered" : "<p>Fire, a primal force, captivates with its flickering flames, evoking both awe and caution. Its dance symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate. In ancient times, fire was a beacon of light and warmth, […]</p>\n" }, "featured_media" : 0, "format" : "standard", "guid" : { "rendered" : "https://yoursite.com/?p=13" }, "id" : 13, "link" : "https://yoursite.com/?p=13", "meta" : { "footnotes" : "" }, "modified" : "2024-02-29T16:45:36", "modified_gmt" : "2024-02-29T16:45:36", "ping_status" : "open", "slug" : "fire-fire", "status" : "publish", "sticky" : false, "tags" : [], "template" : "", "title" : { "rendered" : "Fire" }, "type" : "post" }, }, ... ][ { "_links" : { "about" : [...], "author" : [...], "collection" : [...], "curies" : [...], "predecessor-version" : [...], "replies" : [...], "self" : [...], "version-history" : [...], "wp:attachment" : [...], "wp:term" : [...] }, "author" : 1, "categories" : [...], "comment_status" : "open", "content" : { "protected" : false, "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, "date" : "2024-02-27T12:08:30", "date_gmt" : "2024-02-27T12:08:30", "excerpt" : { "protected" : false, "rendered" : "<p>Fire, a primal force, captivates with its flickering flames, evoking both awe and caution. Its dance symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate. In ancient times, fire was a beacon of light and warmth, […]</p>\n" }, "featured_media" : 0, "format" : "standard", "guid" : { "rendered" : "https://yoursite.com/?p=13" }, "id" : 13, "link" : "https://yoursite.com/?p=13", "meta" : { "footnotes" : "" }, "modified" : "2024-02-29T16:45:36", "modified_gmt" : "2024-02-29T16:45:36", "ping_status" : "open", "slug" : "fire-fire", "status" : "publish", "sticky" : false, "tags" : [], "template" : "", "title" : { "rendered" : "Fire" }, "type" : "post" }, }, ... ]
代表古騰堡單個文章資料的 JSON 物件包含多個欄位,其中內容和摘錄欄位將作為解析為 HTML 字串的古騰堡區塊返回。
- 為了在 Next.js 中正確呈現這些 HTML 內容,我們使用了
dangerouslySetInnerHTML
屬性:const page = async () => {const posts = await getWpPosts();return (<><h1> Headless Blog </h1><div>{posts.map((post) => (<Link href={'/blog/' + post.id} key={post.id}><h2>{post.title.rendered} <span>-></span></h2><div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} /></Link>))}</div></>);};export default page;const page = async () => { const posts = await getWpPosts(); return ( <> <h1> Headless Blog </h1> <div> {posts.map((post) => ( <Link href={'/blog/' + post.id} key={post.id}> <h2> {post.title.rendered} <span>-></span> </h2> <div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} /> </Link> ))} </div> </> ); }; export default page;const page = async () => { const posts = await getWpPosts(); return ( <> <h1> Headless Blog </h1> <div> {posts.map((post) => ( <Link href={'/blog/' + post.id} key={post.id}> <h2> {post.title.rendered} <span>-></span> </h2> <div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} /> </Link> ))} </div> </> ); }; export default page;
在這個更新的元件中,我們對獲取的文章陣列進行對映,生成一個文章摘錄列表。每個摘錄都封裝在一個
Link
元件中,用於導航,顯示文章標題和內容片段。dangerouslySetInnerHTML
屬性用於解析和呈現excerpt.rendered
欄位中包含的 HTML 內容。 - 接下來,在 app 目錄下建立檔案 blog/[id]/page.js。您可以使用資料夾來定義路由。因此,通過建立 blog 資料夾,就定義了 blog 路由。結合動態路由,就能為每篇文章生成路由。
- 每個文章都有一個 ID。您可以使用此 ID 在應用程式中生成其唯一路由,即
/blog/{post_id}
。新增以下程式碼:import Link from 'next/link';export async function generateStaticParams() {const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts');const posts = await res.json();return posts.map((post) => {return {params: {id: post.id.toString(),},};});}export async function getPost(id) {const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts/' + id);const post = await response.json();return post;}import Link from 'next/link'; export async function generateStaticParams() { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts.map((post) => { return { params: { id: post.id.toString(), }, }; }); } export async function getPost(id) { const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts/' + id); const post = await response.json(); return post; }import Link from 'next/link'; export async function generateStaticParams() { const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts'); const posts = await res.json(); return posts.map((post) => { return { params: { id: post.id.toString(), }, }; }); } export async function getPost(id) { const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts/' + id); const post = await response.json(); return post; }
generateStaticParams()
函式在構建時根據每個文章返回的相應 ID 靜態生成路由。getPost()
函式會從 REST API 獲取帶有所傳 ID 的文章的 Gutenberg 資料。前面的章節展示了從 REST API 返回的 Gutenberg 資料解析示例。目前,我們只關注
content.rendered
欄位:[{..."content": {"rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure> class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure> class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a> href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n"},...}][ { ... "content": { "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure> class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure> class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a> href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, ... } ][ { ... "content": { "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure> class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure> class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a> href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n" }, ... } ]
該欄位包含文章的原始 HTML 程式碼。它可以直接使用
dangerouslySetInnerHTML
屬性渲染,如下所示:<div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />
。 - 接下來,你可以通過解析內部連結和調整圖片大小來處理資料。安裝
html-react-parser
包可簡化標籤解析過程:npm install html-react-parser --savenpm install html-react-parser --savenpm install html-react-parser --save
- 在 blog/[id]/page.js 檔案中新增以下程式碼:
import parse, { domToReact } from "html-react-parser";/** We use a regular expression (pattern) to match the specific URL you want to replace.* The (\d+) part captures the numeric ID after ?p=.* Then, we use the replacement string 'data-internal-link="true" href="/blog/$1"',* where $1 is a placeholder for the captured ID.*/export function fixInternalLinks(html_string) {const pattern = /href="https:\/\/yoursite.com\/\?p=(\d+)"/g;const replacement = 'data-internal-link="true" href="/blog/$1"';return html_string.replace(pattern, replacement);}export function parseHtml(html) {// Replace 2+ sequences of '\n' with a single '<br />' tagconst _content = html.replace(/\n{2,}/g, '<br />');const content = fixInternalLinks(_content);const options = {replace: ({ name, attribs, children }) => {// Convert internal links to Next.js Link components.const isInternalLink =name === "a" && attribs["data-internal-link"] === "true";if (isInternalLink) {return (<Link href={attribs.href} {...attribs}>{domToReact(children, options)}</Link>);} else if (name === "img") {attribs["width"] = "250";attribs["height"] = "150";return (<img {...attribs}/>);}},};return parse(content, options);}import parse, { domToReact } from "html-react-parser"; /* * We use a regular expression (pattern) to match the specific URL you want to replace. * The (\d+) part captures the numeric ID after ?p=. * Then, we use the replacement string 'data-internal-link="true" href="/blog/$1"', * where $1 is a placeholder for the captured ID. */ export function fixInternalLinks(html_string) { const pattern = /href="https:\/\/yoursite.com\/\?p=(\d+)"/g; const replacement = 'data-internal-link="true" href="/blog/$1"'; return html_string.replace(pattern, replacement); } export function parseHtml(html) { // Replace 2+ sequences of '\n' with a single '<br />' tag const _content = html.replace(/\n{2,}/g, '<br />'); const content = fixInternalLinks(_content); const options = { replace: ({ name, attribs, children }) => { // Convert internal links to Next.js Link components. const isInternalLink = name === "a" && attribs["data-internal-link"] === "true"; if (isInternalLink) { return ( <Link href={attribs.href} {...attribs}> {domToReact(children, options)} </Link> ); } else if (name === "img") { attribs["width"] = "250"; attribs["height"] = "150"; return ( <img {...attribs}/> ); } }, }; return parse(content, options); }
import parse, { domToReact } from "html-react-parser"; /* * We use a regular expression (pattern) to match the specific URL you want to replace. * The (\d+) part captures the numeric ID after ?p=. * Then, we use the replacement string 'data-internal-link="true" href="/blog/$1"', * where $1 is a placeholder for the captured ID. */ export function fixInternalLinks(html_string) { const pattern = /href="https:\/\/yoursite.com\/\?p=(\d+)"/g; const replacement = 'data-internal-link="true" href="/blog/$1"'; return html_string.replace(pattern, replacement); } export function parseHtml(html) { // Replace 2+ sequences of '\n' with a single '<br />' tag const _content = html.replace(/\n{2,}/g, '<br />'); const content = fixInternalLinks(_content); const options = { replace: ({ name, attribs, children }) => { // Convert internal links to Next.js Link components. const isInternalLink = name === "a" && attribs["data-internal-link"] === "true"; if (isInternalLink) { return ( <Link href={attribs.href} {...attribs}> {domToReact(children, options)} </Link> ); } else if (name === "img") { attribs["width"] = "250"; attribs["height"] = "150"; return ( <img {...attribs}/> ); } }, }; return parse(content, options); }
fixInternalLinks()
函式使用正規表示式從 HTML 字串中查詢 WordPress 網站中的文章連結。在原始 HTML 中,您可以看到文章包含一個List
標籤,其中包含指向網站上其他文章的連結,將這些連結替換為指向靜態網站中路由的內部連結。parseHTML()
函式會發現多個多餘的換行符\n
,並將其替換為<br />
標記。它還能找到內部連結,並將錨標記轉換為 Link 標記。然後,該函式使用標籤屬性調整圖片大小。 - 要為每個動態路由生成主使用者介面,請新增以下程式碼:
export default async function Post({ params }) {const post = await getPost(params.id);const content = parseHtml(post.content.rendered);return (<><h1>{post.title.rendered}</h1><div>{content}</div></>);}export default async function Post({ params }) { const post = await getPost(params.id); const content = parseHtml(post.content.rendered); return ( <> <h1> {post.title.rendered} </h1> <div>{content}</div> </> ); }
export default async function Post({ params }) { const post = await getPost(params.id); const content = parseHtml(post.content.rendered); return ( <> <h1> {post.title.rendered} </h1> <div>{content}</div> </> ); }
從 Gutenberg 資料中解析原始 HTML 後,程式碼會返回代表頁面格式化使用者介面的 JSX。
最後,當您執行專案時,主頁將顯示 WordPress 上的文章列表。此外,當您點選單個文章時,您將看到正確呈現的 Gutenberg 解析內容。
小結
本指南介紹瞭如何通過 WordPress API 將 Gutenberg 區塊內容有效地整合並解析為 HTML。這樣,當您使用無頭 WordPress 時,就可以在前端呈現任何型別的內容。
評論留言