使用 Next.js 创建博客文章页面并实现分页功能/n/n本文将介绍如何使用 Next.js 创建一个博客文章页面,并实现文章分页功能,使用 remarkgray-matter 解析 Markdown 文件,并通过 getStaticProps 获取文章数据和分页信息。/n/n### 1. 项目配置/n/n首先,需要安装必要的依赖:/n/nbash/nnpm install remark remark-html gray-matter/n/n/n然后,在 pages 目录下创建一个名为 posts 的文件夹,并在文件夹内创建一个名为 [slug].js 的文件,用来展示博客文章内容。/n/n### 2. 代码实现/n/njavascript/nimport fs from 'fs';/nimport path from 'path';/nimport matter from 'gray-matter';/nimport { remark } from 'remark';/nimport html from 'remark-html';/nimport Info from '@/components/Info';/n/nexport const info = Info();/nexport const Directory = path.join(process.cwd(), info.path);/n/nexport async function getSortedPosts() {/n // initialize counter to start from the first post/n let num = 1;/n /n const subdirectories = fs.readdirSync(Directory, { withFileTypes: true })/n .filter(dirent => dirent.isDirectory())/n .map(dirent => dirent.name);/n /n const postData = (await Promise.all(subdirectories.map(async (subdirectory) => {/n const directoryPath = path.join(Directory, subdirectory)/n const filenames = fs.readdirSync(directoryPath)/n .filter(filename => filename.endsWith('.md'))/n /n const allPostsData = await Promise.all(filenames.map(async (filename) => {/n const slug = [subdirectory, filename.replace(//.md$/, '').concat('.html')].join('/')/n const fullPath = path.join(Directory, [subdirectory, filename].join('//'))/n const fileContents = fs.readFileSync(fullPath, 'utf8')/n const matterResult = matter(fileContents)/n const contentCount = await remark()/n .use(html, { sanitize: false })/n .process(matterResult.content)/n /n const contCount = contentCount.toString().replace(/<//?(h/d).*>/g, '');/n const NoImages = contCount.replace(/<img[^>]*>/g, '').trim();/n const NoHtml = NoImages.replace(/<//?[^>]+(>|$)/g, '');/n const cnMatches = NoHtml.match(/[/u4e00-/u9fa5]/g) || [];/n const enMatches = NoHtml.match(/[a-zA-Z]+/g) || [];/n const cnCount = cnMatches.length;/n const enCount = enMatches.length;/n const wordCount = cnCount + enCount - info.exclude;/n /n const postData = {/n num,/n slug,/n wordCount,/n ...(matterResult.data as { date: string; title: string })/n };/n /n num++;/n return postData;/n }));/n /n return allPostsData;/n }))) /n .flat()/n .sort((a, b) => (a.date < b.date ? 1 : -1)) // sort by date in descending order/n .map((post, index, array) => {/n // Reverse the numbering so that the first post has the highest number/n post.num = array.length - index;/n return post;/n });/n /n return postData;/n}/n/nexport const getStaticProps: GetStaticProps = async ({ params }) => {/n if (!params || !params.slug) {/n return { notFound: true };/n }/n const originalSlug = params?.slug?.toString().split(',').join('/')/n const slug = originalSlug.replace(//.html$/, '')/n/n const posts = await getSortedPosts();/n const currentPost = posts.find(post => post.slug.toString().split(',').join('/').replace(//.html$/, '') === slug);/n const currentIndex = currentPost?.num ?? 0; // 如果找不到对应文章,则返回 -1/n/n const prevPostIndex = currentIndex - 1;/n const nextPostIndex = currentIndex + 1;/n const prev = prevPostIndex >= 0 ? posts[prevPostIndex] : null;/n const next = nextPostIndex < posts.length ? posts[nextPostIndex] : null;/n console.log(`文章页面:${prevPostIndex}`);/n console.log(`文章页面:${nextPostIndex}`);/n/n const ma = await getPostData(slug as string);/n const chat = await chatGPTData(slug as string);/n/n const { totalPosts, totalWordCount } = await total();/n return {/n props: {/n ma,/n chat,/n totalPosts,/n totalWordCount,/n currentIndex,/n prev,/n next,/n }/n }/n}/n/n// 获取文章内容/nexport async function getPostData(slug) {/n const fullPath = path.join(Directory, slug);/n const fileContents = fs.readFileSync(fullPath, 'utf8');/n const matterResult = matter(fileContents);/n const processedContent = await remark()/n .use(html)/n .process(matterResult.content);/n const contentHtml = processedContent.toString();/n return {/n contentHtml,/n ...matterResult.data,/n };/n}/n/n// 获取 chatGPT 数据/nexport async function chatGPTData(slug) {/n // 根据 slug 获取 chatGPT 数据,具体实现方式需要根据实际情况进行调整/n // 例如,可以调用 chatGPT API 或使用其他方法获取数据/n return {};/n}/n/n// 获取所有文章数量和总字数/nexport async function total() {/n const posts = await getSortedPosts();/n const totalPosts = posts.length;/n const totalWordCount = posts.reduce((sum, post) => sum + post.wordCount, 0);/n return {/n totalPosts,/n totalWordCount/n };/n}/n/n/n### 3. 总结/n/n本文介绍了如何使用 Next.js 创建一个博客文章页面,并实现文章分页功能。该方法使用了 remarkgray-matter 解析 Markdown 文件,并通过 getStaticProps 获取文章数据和分页信息。/n/n希望这篇文章能帮助您创建自己的博客网站!/n/n### 4. 代码解析/n/n- getSortedPosts() 函数:该函数用于获取所有文章数据,并根据日期进行排序。/n - 使用 fs.readdirSync 获取目录下所有子目录;/n - 使用 fs.readdirSync 获取每个子目录下的所有 Markdown 文件;/n - 使用 remarkgray-matter 解析 Markdown 文件并获取文章标题、日期、内容等信息;/n - 计算文章字数;/n - 对文章进行排序,并返回排序后的数组。/n- getStaticProps() 函数:该函数用于获取单个文章页面所需数据,包括文章内容、上一篇文章和下一篇文章等。/n - 获取当前文章的 slug;/n - 从 getSortedPosts() 获取所有文章数据;/n - 通过 slug 找到当前文章;/n - 获取当前文章的索引;/n - 获取上一篇文章和下一篇文章;/n - 使用 getPostData() 获取当前文章内容;/n - 使用 chatGPTData() 获取 chatGPT 数据(如果需要);/n - 使用 total() 获取所有文章数量和总字数;/n - 将所有数据传递给页面组件。/n- getPostData() 函数:该函数用于获取单个文章内容。/n - 使用 fs.readFileSync 获取文章内容;/n - 使用 remarkgray-matter 解析文章内容并获取文章标题、日期、内容等信息;/n - 返回包含文章标题、日期、内容等信息的 JSON 对象。/n- chatGPTData() 函数:该函数用于获取 chatGPT 数据。具体实现方式需要根据实际情况进行调整,例如调用 chatGPT API 或使用其他方法获取数据。/n- total() 函数:该函数用于获取所有文章数量和总字数。/n - 使用 getSortedPosts() 获取所有文章数据;/n - 计算文章数量;/n - 计算所有文章的总字数;/n - 返回包含文章数量和总字数的 JSON 对象。/n/n### 5. 如何获取 num 为 8 的内容?/n/n根据代码逻辑,可以通过以下方式获取 num 为 8 的内容:/n/njavascript/nconst prevPost = prevPostIndex >= 0 ? posts[prevPostIndex] : null;/nconst prevPostNum = prevPost?.num;/nconst prevPostContent = posts.find(post => post.num === prevPostNum);/n/n/n首先获取到 prev 对应的整个对象 prevPost,然后从 prevPost 中获取到 num 的值 prevPostNum,最后通过 posts.find 方法找到 num 值为 prevPostNum 的对象并赋值给 prevPostContent。这样就可以获取到 num 为 8 的内容了。/n

Next.js 博客文章页面生成与分页:使用 remark 和 gray-matter 解析 Markdown 文件

原文地址: https://www.cveoy.top/t/topic/mAW3 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录