[site/content][s]: add markdown guide
This commit is contained in:
parent
3f06aa3f01
commit
7c21993b92
169
site/content/howto/markdown.md
Normal file
169
site/content/howto/markdown.md
Normal file
@ -0,0 +1,169 @@
|
||||
# How to add markdown-based content pages?
|
||||
|
||||
## Add content layer to your app
|
||||
|
||||
Create a folder where you'll keep your markdown files and add some markdown files to it.
|
||||
|
||||
```sh
|
||||
cd my-portaljs-project
|
||||
mkdir content
|
||||
# touch content/index.md ...
|
||||
```
|
||||
|
||||
Install [MarkdownDB](https://github.com/datopian/markdowndb) package:
|
||||
|
||||
```
|
||||
npm i @flowershow/markdowndb
|
||||
```
|
||||
|
||||
And add the following to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"mddb": "mddb <path-to-your-content-folder>",
|
||||
"prebuild": "npm run mddb"
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can give it a go by running `npm run mddb`. You should see a `markdown.db` file created in the root of your project. You can inspect it with any SQLite viewer or in the command line. In the `files` table you should see all your markdown files from your content folder.
|
||||
|
||||
Now, once the data is in the database, you can add the following script to your project (e.g. in `/lib` folder). It will allow you to establish a single connection to the database and use it across your app.
|
||||
|
||||
```ts
|
||||
// lib/mddb.ts
|
||||
import { MarkdownDB } from "@flowershow/markdowndb";
|
||||
|
||||
// path to the markdown.db file created by the mddb script
|
||||
const dbPath = "markdown.db";
|
||||
|
||||
const client = new MarkdownDB({
|
||||
client: "sqlite3",
|
||||
connection: {
|
||||
filename: dbPath,
|
||||
},
|
||||
});
|
||||
|
||||
const clientPromise = client.init();
|
||||
|
||||
export default clientPromise;
|
||||
```
|
||||
|
||||
Now you can import it across your project to query the database, e.g.:
|
||||
|
||||
```ts
|
||||
import clientPromise from "@/lib/mddb";
|
||||
|
||||
const mddb = await clientPromise;
|
||||
const blogs = await mddb.getFiles({
|
||||
folder: "blog",
|
||||
extensions: ["md", "mdx"],
|
||||
});
|
||||
```
|
||||
|
||||
## Write a markdown parser
|
||||
|
||||
Install [next-mdx-remote](https://github.com/hashicorp/next-mdx-remote) package, which we'll first use to parse markdown files and then to render them in Next.js app.
|
||||
|
||||
```sh
|
||||
npm i next-mdx-remote
|
||||
```
|
||||
|
||||
Create the following basic parser for your markdown files, e.g. in `/lib/markdown.ts`:
|
||||
|
||||
```ts
|
||||
import matter from "gray-matter";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { serialize } from "next-mdx-remote/serialize";
|
||||
|
||||
|
||||
const parse = async function (source) {
|
||||
const { content } = matter(source);
|
||||
|
||||
const mdxSource = await serialize(
|
||||
{ value: content },
|
||||
{
|
||||
mdxOptions: {
|
||||
remarkPlugins: [
|
||||
remarkGfm,
|
||||
// ... your remark plugins
|
||||
],
|
||||
rehypePlugins: [
|
||||
// ... your plugins
|
||||
],
|
||||
format,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
mdxSource
|
||||
};
|
||||
};
|
||||
|
||||
export default parse;
|
||||
|
||||
```
|
||||
|
||||
## Import, parse and render your markdown files
|
||||
|
||||
Create a page in the `/pages` folder that will render your markdown content, e.g. `pages/blog/[[...slug]].tsx`:
|
||||
|
||||
```tsx
|
||||
import fs from "fs";
|
||||
|
||||
import { MdxRemote } from "next-mdx-remote";
|
||||
import clientPromise from "@/lib/mddb.mjs";
|
||||
import parse from "@/lib/markdown";
|
||||
|
||||
|
||||
export default function Page({ source }) {
|
||||
source = JSON.parse(source);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MdxRemote source={source} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// Import metadata of a file matching the static path and return its parsed source and frontmatter object
|
||||
export const getStaticProps = async ({ params }) => {
|
||||
const urlPath = params?.slug ? (params.slug as string[]).join("/") : "/";
|
||||
|
||||
const mddb = await clientPromise;
|
||||
const dbFile = await mddb.getFileByUrl(urlPath);
|
||||
const filePath = dbFile!.file_path;
|
||||
// const frontMatter = dbFile!.metadata ?? {};
|
||||
|
||||
const source = fs.readFileSync(filePath, { encoding: "utf-8" });
|
||||
const { mdxSource } = await parse(source, "mdx", {});
|
||||
|
||||
return {
|
||||
props: {
|
||||
source: JSON.stringify(mdxSource),
|
||||
// frontMatter
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Import metadata of your markdown files from MarkdownDB and return a list of static paths
|
||||
export const getStaticPaths = async () => {
|
||||
const mddb = await clientPromise;
|
||||
const allDocuments = await mddb.getFiles({ extensions: ["md", "mdx"] });
|
||||
const paths = allDocuments
|
||||
.map((page) => {
|
||||
const url = decodeURI(page.url_path);
|
||||
const parts = url.split("/");
|
||||
return { params: { slug: parts } };
|
||||
});
|
||||
|
||||
return {
|
||||
paths,
|
||||
fallback: false,
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user