首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Next.JS中的嵌套文件夹中显示标记文件?

如何在Next.JS中的嵌套文件夹中显示标记文件?
EN

Stack Overflow用户
提问于 2021-09-09 16:58:14
回答 1查看 1.3K关注 0票数 2

在我的Next.JS项目中,我在许多文件夹中分发了许多Markdown文件,这些文件夹被视为类别。因此,我在项目的根目录中有名为“CategoryOne”和“CategoryTwo”的文件夹(与node_modules、pages、public的级别相同)。这些文件夹中的每个都包含一些Markdown文件。

我有一个名为“ .md ”的页面,它应该呈现来自“CategoryOne”和“.md 2”的所有.md文件。正如我必须要得到的那样, As 是一个包含index.js (将所有.md文件作为文章列出)和slug.js (显示单击的文章)的文件夹。

让我们看一看!

pages/articles/index.js

代码语言:javascript
运行
复制
import React, { useState } from 'react'
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { useRouter } from 'next/router'

export default function Blog({ posts, postsTwo }) {
    const router = useRouter()
    if (router.isFallback) {
        return <div>Loading...</div>
    }
    return (
        <>
            {/* Maps articles from both Categories */}
        </>
    )
}

export async function getStaticProps() {
    const files = fs.readdirSync(path.join('CategoryOne'))
    const posts = files.map((filename) => {
        const slug = filename.replace('.md', '')
        const markdownWithMeta = fs.readFileSync(
            path.join('CategoryOne', filename),
            'utf-8'
        )
        const { data: frontmatter } = matter(markdownWithMeta)

        return {
            slug,
            frontmatter,
        }
    })

    const files2 = fs.readdirSync(path.join('CategoryTwo'))
    const posts2 = files2.map((filename) => {
        const slug2 = filename.replace('.md', '')
        const markdownWithMeta2 = fs.readFileSync(
            path.join('CategoryTwo', filename),
            'utf-8'
        )
        const { data: frontmatter } = matter(markdownWithMeta2)

        return {
            slug2,
            frontmatter,
        }
    })

    return {
        props: {
            posts: posts,
            postsTwo: posts2,
        },
    }
}

[slug].js

代码语言:javascript
运行
复制
import React, { useState, useEffect } from 'react'
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import marked from 'marked'
import { useRouter } from 'next/router'

export default function PostPage({
    frontmatter: { title, date, reading_time, category },
    slug,
    content,
    posts,
}) {
    
    if (router.isFallback) {
        return <div>Loading...</div>
    }

    return (
        <>
            <div>
                <h1>{title}</h1>
                <p>{date} • {reading_time}</p>
                <div>
                    <div dangerouslySetInnerHTML={{__html: marked(content)}}></div>
                </div>
           </div>
        </>
    )
}

export async function getStaticPaths() {
    const files = fs.readdirSync(path.join('CategoryOne'))
    const paths = files.map((filename) => ({
        params: {
            slug: filename.replace('.md', ''),
        },
    }))

    return {
        paths,
        fallback: false,
    }
}

export async function getStaticProps({ params: { slug } }) {
    const files = fs.readdirSync(path.join('CategoryOne'))
    const markdownWithMeta = fs.readFileSync(
        path.join('CategoryOne', slug + '.md'),
        'utf-8'
    )
    const { data: frontmatter, content } = matter(markdownWithMeta)
    const posts = files.map((filename) => {
        const slug = filename.replace('.md', '')
        const markdownWithMeta = fs.readFileSync(
            path.join('CategoryOne', filename),
            'utf-8'
        )
        const { data: frontmatter } = matter(markdownWithMeta)

        return {
            slug,
            frontmatter,
        }
    })
    return {
        props: {
            frontmatter,
            slug,
            content,
            posts,
        },
    }
}

当我点击“CategoryTwo”中的一篇文章时,我得到了一个404错误。这是因为在slug.js中,我只能返回“类别一”中的段塞。

在index.js中,getStaticProps()太长了,我希望得到这个函数递归。因为我认为将类别文件夹放入一个名为“post”的文件夹会更好。因此,如果有更多的类别,我可以让所有的.md文件白化,用它们的名字称呼它们。

代码语言:javascript
运行
复制
/posts
  |______ /CategoryOne
  |______ /CategoryTwo

总之,我们必须将重点放在getStaticProps()、getStaticPaths()和文件系统libray上,以便递归地从子目录中列出文件。

2021] [编辑·9月10日]

我在我的utils/index.js中做了两个函数。第一个是子文件夹,第二个是每个子文件夹。

代码语言:javascript
运行
复制
import { readdir } from 'fs/promises';
const postsDirectory = path.join(process.cwd(), 'posts');

export function getDirectories(postsDirectory) {
  return fs
    .readdirSync(postsDirectory, { withFileTypes: true })
    .filter((dirent) => dirent.isDirectory())
    .map((dirent) => dirent.name);
}

export async function getAllFiles() {
  const test = getDirectories(postsDirectory);
  let table = [];
  for (const folder of test) {
    const subfolder = path.join(postsDirectory, folder);
    let files = await readdir(subfolder);
    for (const file of files) {
      table.push({ file: file, folder: folder });
    }
  }
  return table;
}

/* Result

[
  { file: 'markdown-one-1.md', folder: 'CategoryOne' },
  { file: 'markdown-one-2.md', folder: 'CategoryOne' },
  { file: 'markdown-one-1.md', folder: 'CategoryTwo' },
  { file: 'markdown-one-2.md', folder: 'CategoryTwo' },
]

*/

我发现,如果在posts文件夹中有一些子文件夹,那么在posts页面中应该有与下面的模式相同的内容:

代码语言:javascript
运行
复制
├── node_modules
├── package.json
├── pages
│   ├── index.js
│   ├── _app.js
│   └── posts
│       ├── CategoryOne
│           ├── [id].js //to display .md files of CategoryOne
│       ├── CategoryTwo
│           ├── [id].js //to display .md files of CategoryTwo
├── ..
└── posts
    ├── CategoryOne
    │   ├── markdown-one-1.md
    │   ├── markdown-one-2.md
    │   ├── markdown-one-3.md
    │   └── ..
    └── CategoryTwo
        ├── markdown-two-1.md
        ├── markdown-two-2.md
        ├── markdown-two-3.md
        └── ..

应该有一种方法来自动创建这些id.js文件,具体取决于您有多少子文件夹。

EN

回答 1

Stack Overflow用户

发布于 2021-09-09 21:08:35

就像您说的,最好将您的类别和它们的文章放在它们自己的目录中。我知道您提到过递归地这样做,但是如果这不是绝对的要求,我建议使用格罗布

假设您有以下文件结构

代码语言:javascript
运行
复制
├── node_modules
├── package.json
├── ..
└── posts
    ├── CategoryOne
    │   ├── markdown-one-1.md
    │   ├── markdown-one-2.md
    │   ├── markdown-one-3.md
    │   └── ..
    └── CategoryTwo
        ├── markdown-two-1.md
        ├── markdown-two-2.md
        ├── markdown-two-3.md
        └── ..

然后,您可以在getStaticProps和/或getStaticPaths方法中执行类似的操作:

代码语言:javascript
运行
复制
const glob = require('glob');

glob('posts/**/*.md', (err, files) => {
    console.log({files});

    /*
     * will produce:
     * {
     *     files: [
     *       'posts/CategoryOne/markdown-one-1.md',
     *       'posts/CategoryOne/markdown-one-2.md',
     *       'posts/CategoryOne/markdown-one-3.md',
     *       'posts/CategoryTwo/markdown-two-1.md',
     *       'posts/CategoryTwo/markdown-two-2.md',
     *       'posts/CategoryTwo/markdown-two-3.md'
     *     ]
     * }
     */

});

然后,您只需要对每个文件进行split('/'),组织类别/文件名,并将它们作为支持返回。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69122134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档