You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							95 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
	
	
							95 lines
						
					
					
						
							2.8 KiB
						
					
					
				| import { format, parseISO } from 'date-fns';
 | |
| import fs from 'fs';
 | |
| import matter from 'gray-matter';
 | |
| import { GetStaticPaths, GetStaticProps } from 'next';
 | |
| import { serialize } from 'next-mdx-remote/serialize';
 | |
| import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote';
 | |
| import Head from 'next/head';
 | |
| import Image from 'next/image';
 | |
| import Link from 'next/link';
 | |
| import path from 'path';
 | |
| import React from 'react';
 | |
| import rehypeAutolinkHeadings from 'rehype-autolink-headings';
 | |
| import rehypeSlug from 'rehype-slug';
 | |
| import { Layout } from '../../components/index';
 | |
| import { MetaProps } from '../../types/layout';
 | |
| import { PostType } from '../../types/post';
 | |
| import { postFilePaths, POSTS_PATH } from '../../utils/mdxUtils';
 | |
| 
 | |
| // Custom components/renderers to pass to MDX.
 | |
| // Since the MDX files aren't loaded by webpack, they have no knowledge of how
 | |
| // to handle import statements. Instead, you must include components in scope
 | |
| // here.
 | |
| const components = {
 | |
|   Head,
 | |
|   Image,
 | |
|   Link,
 | |
| };
 | |
| 
 | |
| type PostPageProps = {
 | |
|   source: MDXRemoteSerializeResult;
 | |
|   frontMatter: PostType;
 | |
| };
 | |
| 
 | |
| const PostPage = ({ source, frontMatter }: PostPageProps): JSX.Element => {
 | |
|   const customMeta: MetaProps = {
 | |
|     title: `${frontMatter.title} - RoboTop`,
 | |
|     description: frontMatter.description,
 | |
|     image: `${frontMatter.image}`,
 | |
|     date: frontMatter.date,
 | |
|     type: 'article',
 | |
|   };
 | |
|   return (
 | |
|     <Layout customMeta={customMeta}>
 | |
|       <article className="max-w">
 | |
|         <h1 className="mb-3 text-gray-900 dark:text-white">
 | |
|           {frontMatter.title}
 | |
|         </h1>
 | |
|         <p className="mb-10 text-sm text-gray-500 dark:text-gray-400">
 | |
|           {format(parseISO(frontMatter.date), 'MMMM dd, yyyy')}
 | |
|         </p>
 | |
|         <div className="prose dark:prose-dark">
 | |
|           <MDXRemote {...source} components={components} />
 | |
|         </div>
 | |
|       </article>
 | |
|     </Layout>
 | |
|   );
 | |
| };
 | |
| 
 | |
| export const getStaticProps: GetStaticProps = async ({ params }) => {
 | |
|   const postFilePath = path.join(POSTS_PATH, `${params.slug}.mdx`);
 | |
|   const source = fs.readFileSync(postFilePath);
 | |
| 
 | |
|   const { content, data } = matter(source);
 | |
| 
 | |
|   const mdxSource = await serialize(content, {
 | |
|     // Optionally pass remark/rehype plugins
 | |
|     mdxOptions: {
 | |
|       remarkPlugins: [require('remark-code-titles')],
 | |
|       rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings],
 | |
|     },
 | |
|     scope: data,
 | |
|   });
 | |
| 
 | |
|   return {
 | |
|     props: {
 | |
|       source: mdxSource,
 | |
|       frontMatter: data,
 | |
|     },
 | |
|   };
 | |
| };
 | |
| 
 | |
| export const getStaticPaths: GetStaticPaths = async () => {
 | |
|   const paths = postFilePaths
 | |
|     // Remove file extensions for page paths
 | |
|     .map((path) => path.replace(/\.mdx?$/, ''))
 | |
|     // Map the path into the static paths object required by Next.js
 | |
|     .map((slug) => ({ params: { slug } }));
 | |
| 
 | |
|   return {
 | |
|     paths,
 | |
|     fallback: false,
 | |
|   };
 | |
| };
 | |
| 
 | |
| export default PostPage;
 | |
| 
 |