Skip to content

Commit e97f0ad

Browse files
committed
add support to mdx
1 parent d7d43b3 commit e97f0ad

15 files changed

+1400
-34
lines changed

next.config.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1+
const withMDX = require("@next/mdx")({
2+
extension: /\.mdx?$/,
3+
options: {
4+
remarkPlugins: [],
5+
rehypePlugins: [],
6+
},
7+
});
8+
19
/** @type {import('next').NextConfig} */
210
const nextConfig = {
11+
pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"],
312
images: {
413
dangerouslyAllowSVG: true,
514
domains: ["firebasestorage.googleapis.com", "flagicons.lipis.dev"],
615
},
716
};
817

9-
module.exports = nextConfig;
18+
module.exports = withMDX(nextConfig);

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
},
1414
"dependencies": {
1515
"@formatjs/intl-localematcher": "^0.4.0",
16+
"@mdx-js/loader": "^2.3.0",
17+
"@mdx-js/react": "^2.3.0",
18+
"@mdx-js/runtime": "^1.6.22",
19+
"@next/mdx": "^13.4.19",
1620
"@types/node": "20.4.5",
1721
"@types/react": "18.2.17",
1822
"@types/react-dom": "18.2.7",
@@ -27,6 +31,7 @@
2731
"negotiator": "^0.6.3",
2832
"next": "13.4.12",
2933
"next-i18next": "^14.0.0",
34+
"next-mdx-remote": "^4.4.1",
3035
"postcss": "8.4.27",
3136
"react": "18.2.0",
3237
"react-dom": "18.2.0",

src/app/[lang]/globals.css

+9
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,13 @@
55
::selection {
66
color: white;
77
background: theme("colors.primary");
8+
}
9+
10+
.post-content a {
11+
color: theme("colors.primary");
12+
text-decoration: underline;
13+
}
14+
15+
.post-content a:hover {
16+
color: theme("colors.primaryAlt");
817
}

src/app/[lang]/posts/[slug]/getPostService.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { serialize } from "next-mdx-remote/serialize";
2+
13
import { getPostBySlug } from "@/lib/getPosts";
2-
import markdownToHtml from "@/lib/markdownToHtml";
34

45
async function getPost(slug: string, lang: string) {
56
const post = getPostBySlug(
@@ -10,7 +11,7 @@ async function getPost(slug: string, lang: string) {
1011

1112
if (!post) return null;
1213

13-
const content = await markdownToHtml(post.content || "");
14+
const content = await serialize(post.content || "");
1415

1516
return {
1617
...post,

src/app/[lang]/posts/[slug]/page.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { notFound, redirect } from "next/navigation";
1+
import { redirect } from "next/navigation";
22

33
import Container from "@/components/Container";
44
import { Post } from "@/interfaces/Post";
55
import getPost from "./getPostService";
6+
import PostContent from "@/components/PostContent";
67

78
type Props = {
89
params: { slug: string; lang: string };
@@ -32,10 +33,7 @@ export default async function PostPage({ params: { slug, lang } }: Props) {
3233
</time>
3334
</header>
3435

35-
<div
36-
className="prose mt-10"
37-
dangerouslySetInnerHTML={{ __html: post.content || "" }}
38-
/>
36+
<PostContent content={post.content} />
3937
</article>
4038
</div>
4139
)}

src/components/PostContent.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"use client";
2+
3+
import { MDXRemote } from "next-mdx-remote";
4+
5+
import Link from "./Link";
6+
7+
export default function PostContent({ content }: { content: any }) {
8+
return (
9+
<div className="mt-6">
10+
<MDXRemote {...content} components={{ Link }} />
11+
</div>
12+
);
13+
}

src/interfaces/Post.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export type Post = {
33
title?: string;
44
author?: string;
55
date?: Date;
6-
content?: string;
6+
content?: any;
77
excerpt?: string;
88
[key: string]: any;
9-
};
9+
};

src/lib/getPosts.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export function getPostBySlug(
1616
lang: string,
1717
) {
1818
try {
19-
const realSlug = slug.replace(/\.md$/, "");
20-
const fullPath = join(`${postsDirectory}/${lang}`, `${realSlug}.md`);
19+
const realSlug = slug.replace(/\.mdx$/, "");
20+
const fullPath = join(`${postsDirectory}/${lang}`, `${realSlug}.mdx`);
2121
const fileContents = fs.readFileSync(fullPath, "utf8");
2222

2323
const { data, content } = matter(fileContents);

src/lib/markdownToHtml.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { VFileCompatible } from "vfile";
22
import { remark } from "remark";
3-
import html from "remark-html";
43

54
export default async function markdownToHtml(markdown: VFileCompatible) {
6-
const result = await remark().use(html).process(markdown);
5+
const result = await remark().process(markdown);
76
return result.toString();
8-
}
7+
}
File renamed without changes.
File renamed without changes.

src/posts/es/rpcide.md

-5
This file was deleted.

src/posts/es/rpcide.mdx

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "El RPCIDE"
3+
excerpt: ""
4+
date: "2023-08-26"
5+
---
6+
7+
El RPCIDE es un <Link href="https://es.wikipedia.org/wiki/Entorno_de_desarrollo_integrado" target="_blank">IDE</Link> enfocado en la programación competitiva.

tailwind.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
extend: {
1111
colors: {
1212
primary: "#20BF55",
13+
primaryAlt: "#53E383",
1314
},
1415
},
1516
},

0 commit comments

Comments
 (0)