From e545a596ec28be1dfd246d69bf2e97f76d8dbd63 Mon Sep 17 00:00:00 2001 From: rei Date: Thu, 29 Dec 2022 13:42:04 +0100 Subject: [PATCH] added projects --- content/projects/first-project.md | 16 ++ content/projects/markdown-test.md | 241 ++++++++++++++++++++++++++++++ pages/blog/[slug].tsx | 24 +-- pages/blog/index.tsx | 18 +-- pages/project/[slug].tsx | 79 ++++++++++ pages/projects/index.tsx | 76 ++++++++++ styles/globals.css | 5 + utils/general.ts | 10 ++ utils/markdown.ts | 37 ++++- 9 files changed, 474 insertions(+), 32 deletions(-) create mode 100644 content/projects/markdown-test.md create mode 100644 pages/project/[slug].tsx create mode 100644 pages/projects/index.tsx create mode 100644 utils/general.ts diff --git a/content/projects/first-project.md b/content/projects/first-project.md index e69de29..1279f7a 100644 --- a/content/projects/first-project.md +++ b/content/projects/first-project.md @@ -0,0 +1,16 @@ +--- +title: "My First Project" +date: 29.12.2022 +author: kookroach +authorLink: https://git.peroxy.dev/kookroach +description: Short description +thumbnail: https://images.unsplash.com/photo-1640539984026-c1b0d7c5d4b5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1332&q=80 +--- + +# First project + +This is a project + +You can add pics + +![Foo](https://images.unsplash.com/photo-1593508512255-86ab42a8e620?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=578&q=80) \ No newline at end of file diff --git a/content/projects/markdown-test.md b/content/projects/markdown-test.md new file mode 100644 index 0000000..2b9dd23 --- /dev/null +++ b/content/projects/markdown-test.md @@ -0,0 +1,241 @@ +--- +title: "Markdown test" +date: 29.12.2022 +author: kookroach +authorLink: https://git.peroxy.dev/kookroach +description: Short description +--- + +# h1 Heading 8-) +## h2 Heading +### h3 Heading +#### h4 Heading +##### h5 Heading +###### h6 Heading + + +## Horizontal Rules + +___ + +--- + +*** + + +## Typographic replacements + +Enable typographer option to see result. + +(c) (C) (r) (R) (tm) (TM) (p) (P) +- + +test.. test... test..... test?..... test!.... + +!!!!!! ???? ,, -- --- + +"Smartypants, double quotes" and 'single quotes' + + +## Emphasis + +**This is bold text** + +__This is bold text__ + +*This is italic text* + +_This is italic text_ + +~~Strikethrough~~ + + +## Blockquotes + + +> Blockquotes can also be nested... +>> ...by using additional greater-than signs right next to each other... +> > > ...or with spaces between arrows. + + +## Lists + +Unordered + ++ Create a list by starting a line with `+`, `-`, or `*` ++ Sub-lists are made by indenting 2 spaces: + - Marker character change forces new list start: + * Ac tristique libero volutpat at + + Facilisis in pretium nisl aliquet + - Nulla volutpat aliquam velit ++ Very easy! + +Ordered + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + + +1. You can use sequential numbers... +1. ...or keep all the numbers as `1.` + +Start numbering with offset: + +57. foo +1. bar + + +## Code + +Inline `code` + +Indented code + + // Some comments + line 1 of code + line 2 of code + line 3 of code + + +Block code "fences" + +``` +Sample text here... +``` + +Syntax highlighting + +``` js +var foo = function (bar) { + return bar++; +}; + +console.log(foo(5)); +``` + +## Tables + +| Option | Description | +| ------ | ----------- | +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + +Right aligned columns + +| Option | Description | +| ------:| -----------:| +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + + +## Links + +[link text](http://dev.nodeca.com) + +[link with title](http://nodeca.github.io/pica/demo/ "title text!") + +Autoconverted link https://github.com/nodeca/pica (enable linkify to see) + + +## Images + +![Minion](https://octodex.github.com/images/minion.png) +![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") + +Like links, Images also have a footnote style syntax + +![Alt text][id] + +With a reference later in the document defining the URL location: + +[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" + + +## Plugins + +The killer feature of `markdown-it` is very effective support of +[syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin). + + +### [Emojies](https://github.com/markdown-it/markdown-it-emoji) + +> Classic markup: :wink: :crush: :cry: :tear: :laughing: :yum: +> +> Shortcuts (emoticons): :-) :-( 8-) ;) + +see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji. + + +### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup) + +- 19^th^ +- H~2~O + + +### [\](https://github.com/markdown-it/markdown-it-ins) + +++Inserted text++ + + +### [\](https://github.com/markdown-it/markdown-it-mark) + +==Marked text== + + +### [Footnotes](https://github.com/markdown-it/markdown-it-footnote) + +Footnote 1 link[^first]. + +Footnote 2 link[^second]. + +Inline footnote^[Text of inline footnote] definition. + +Duplicated footnote reference[^second]. + +[^first]: Footnote **can have markup** + + and multiple paragraphs. + +[^second]: Footnote text. + + +### [Definition lists](https://github.com/markdown-it/markdown-it-deflist) + +Term 1 + +: Definition 1 +with lazy continuation. + +Term 2 with *inline markup* + +: Definition 2 + + { some code, part of Definition 2 } + + Third paragraph of definition 2. + +_Compact style:_ + +Term 1 + ~ Definition 1 + +Term 2 + ~ Definition 2a + ~ Definition 2b + + +### [Abbreviations](https://github.com/markdown-it/markdown-it-abbr) + +This is HTML abbreviation example. + +It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on. + +*[HTML]: Hyper Text Markup Language + +### [Custom containers](https://github.com/markdown-it/markdown-it-container) + +::: warning +*here be dragons* +::: diff --git a/pages/blog/[slug].tsx b/pages/blog/[slug].tsx index 2cd8313..98ff5fc 100644 --- a/pages/blog/[slug].tsx +++ b/pages/blog/[slug].tsx @@ -3,7 +3,7 @@ import fs from "fs"; import { ParsedUrlQuery } from "querystring"; import { BLOGS_PATH, - getFileContentBySlug, + getBlogContentBySlug, renderMarkdown, } from "../../utils/markdown"; import { MarkdownRenderingResult } from "../../types/types"; @@ -27,15 +27,17 @@ export const BlogArticle = ({ frontMatter, html }: MarkdownRenderingResult) => { {date}
{title}
-
- By{" "} - {authorLink && ( - - @{author} - - )} - {!authorLink && @{author}} -
+ {author && ( +
+ By{" "} + {authorLink && ( + + @{author} + + )} + {!authorLink && @{author}} +
+ )}
{description}
= async () => { export const getStaticProps: GetStaticProps = async ({ params, }) => { - const markdownContent = getFileContentBySlug(params?.slug as string); + const markdownContent = getBlogContentBySlug(params?.slug as string); const renderedHTML = await renderMarkdown(markdownContent.content); return { props: { diff --git a/pages/blog/index.tsx b/pages/blog/index.tsx index c13445e..06eeba6 100644 --- a/pages/blog/index.tsx +++ b/pages/blog/index.tsx @@ -1,8 +1,9 @@ import { GetServerSideProps } from "next"; import { MainLayout } from "../../layouts/MainLayout"; -import { BlogPost, getAllFilesFrontMatter } from "../../utils/markdown"; +import { Post, getAllBlogsFrontMatter } from "../../utils/markdown"; import { FrontMatter } from "../../types/types"; import Link from "next/link"; +import { formatDate } from "../../utils/general"; export interface BasicBlogProps extends FrontMatter { title: string; @@ -13,19 +14,10 @@ export interface BasicBlogProps extends FrontMatter { } const BlogCard = ({ blog, slug }: { blog: BasicBlogProps; slug: string }) => { - const format = (date: string) => { - const [day, month, year] = date.split("."); - const d = new Date(`${year}-${month}-${day}`); - return d.toLocaleDateString("en-US", { - month: "long", - day: "numeric", - year: "numeric", - }); - }; return (
- {format(blog.date)} + {formatDate(blog.date)}

{blog.title}

{blog.description}

@@ -38,7 +30,7 @@ const BlogCard = ({ blog, slug }: { blog: BasicBlogProps; slug: string }) => { ); }; -const Blog = ({ posts }: { posts: BlogPost[] }) => { +const Blog = ({ posts }: { posts: Post[] }) => { return (

Blog

@@ -57,7 +49,7 @@ const Blog = ({ posts }: { posts: BlogPost[] }) => { }; export const getServerSideProps: GetServerSideProps = async () => { - const posts = getAllFilesFrontMatter(); + const posts = getAllBlogsFrontMatter(); return { props: { posts, diff --git a/pages/project/[slug].tsx b/pages/project/[slug].tsx new file mode 100644 index 0000000..a5571b6 --- /dev/null +++ b/pages/project/[slug].tsx @@ -0,0 +1,79 @@ +import { GetStaticPaths, GetStaticProps } from "next"; +import fs from "fs"; +import { ParsedUrlQuery } from "querystring"; +import { + getProjectContentBySlug, + PROJECTS_PATH, + renderMarkdown, +} from "../../utils/markdown"; +import { MarkdownRenderingResult } from "../../types/types"; +import { MainLayout } from "../../layouts/MainLayout"; +import Link from "next/link"; +import { IoMdArrowRoundBack as BackIcon } from "react-icons/io"; +import { BasicProjectProps } from "../projects"; + +export const ProjectArticle = ({ + frontMatter, + html, +}: MarkdownRenderingResult) => { + const { title, author, date, description, authorLink } = + frontMatter as BasicProjectProps; + return ( + + + + +
+ {date} +
+
{title}
+ {author && ( +
+ By{" "} + {authorLink && ( + + @{author} + + )} + {!authorLink && @{author}} +
+ )} +
{description}
+
+ + ); +}; +interface ProjectProps extends ParsedUrlQuery { + slug: string; +} +export const getStaticPaths: GetStaticPaths = async () => { + const paths = fs + .readdirSync(PROJECTS_PATH) + .map((path) => path.replace(/\.mdx?$/, "")) + .map((slug) => ({ params: { slug } })); + + return { + paths, + fallback: false, + }; +}; + +export const getStaticProps: GetStaticProps = async ({ + params, +}) => { + const markdownContent = getProjectContentBySlug(params?.slug as string); + const renderedHTML = await renderMarkdown(markdownContent.content); + return { + props: { + frontMatter: markdownContent.frontMatter, + html: renderedHTML, + }, + }; +}; +export default ProjectArticle; diff --git a/pages/projects/index.tsx b/pages/projects/index.tsx new file mode 100644 index 0000000..cf4b193 --- /dev/null +++ b/pages/projects/index.tsx @@ -0,0 +1,76 @@ +import { GetServerSideProps } from "next"; +import { MainLayout } from "../../layouts/MainLayout"; +import { Post, getAllProjectsFrontMatter } from "../../utils/markdown"; +import { FrontMatter } from "../../types/types"; +import Link from "next/link"; +import { formatDate } from "../../utils/general"; + +export interface BasicProjectProps extends FrontMatter { + title: string; + description: string; + date: string; + author: string; + authorLink: string; + thumbnail: string; +} + +const ProjectCard = ({ + project, + slug, +}: { + project: BasicProjectProps; + slug: string; +}) => { + return ( +
+
+
+ {formatDate(project.date)} +
+

{project.title}

+

{project.description}

+ + + +
+ {project.thumbnail && ( + {`${slug}-thumbnail`} + )} +
+ ); +}; + +const Projects = ({ posts }: { posts: Post[] }) => { + return ( + +

Projects

+
+
+ {posts.map((post, index) => ( + + ))} +
+ + ); +}; + +export const getServerSideProps: GetServerSideProps = async () => { + const posts = getAllProjectsFrontMatter(); + return { + props: { + posts, + }, + }; +}; + +export default Projects; diff --git a/styles/globals.css b/styles/globals.css index ef8cac3..0a81cf0 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -5,3 +5,8 @@ body { @apply dark:bg-gradient-dark dark:text-primary-text bg-white text-gradient-dark xl:w-2/3 w-11/12 mx-auto; } + +.prose { + margin: 0; + min-width: 100%; +} diff --git a/utils/general.ts b/utils/general.ts new file mode 100644 index 0000000..7969ba6 --- /dev/null +++ b/utils/general.ts @@ -0,0 +1,10 @@ +export const formatDate = (date: string) => { + if (!date) return null; + const [day, month, year] = date.split("."); + const d = new Date(`${year}-${month}-${day}`); + return d.toLocaleDateString("en-US", { + month: "long", + day: "numeric", + year: "numeric", + }); +}; diff --git a/utils/markdown.ts b/utils/markdown.ts index 64c8576..cc8e4b5 100644 --- a/utils/markdown.ts +++ b/utils/markdown.ts @@ -6,8 +6,13 @@ import { remark } from "remark"; import html from "remark-html"; export const BLOGS_PATH = join(process.cwd(), "content/blogs"); +export const PROJECTS_PATH = join(process.cwd(), "content/projects"); +export interface Post { + frontMatter: FrontMatter; + slug: string; +} -export const getFileContentBySlug = (slug: string): MarkdownDocument => { +export const getBlogContentBySlug = (slug: string): MarkdownDocument => { const filepath = join(BLOGS_PATH, `${slug}.md` || `${slug}.mdx`); const filecontents = fs.readFileSync(filepath); @@ -18,18 +23,34 @@ export const getFileContentBySlug = (slug: string): MarkdownDocument => { content: content, }; }; +export const getProjectContentBySlug = (slug: string): MarkdownDocument => { + const filepath = join(PROJECTS_PATH, `${slug}.md` || `${slug}.mdx`); + const filecontents = fs.readFileSync(filepath); -export interface BlogPost { - frontMatter: FrontMatter; - slug: string; -} + const { data, content } = matter(filecontents); -export const getAllFilesFrontMatter = (): BlogPost[] => { + return { + frontMatter: data, + content: content, + }; +}; + +export const getAllBlogsFrontMatter = (): Post[] => { const files = fs.readdirSync(BLOGS_PATH); - return files.reduce((allPosts: BlogPost[], postSlug: string) => { + return files.reduce((allPosts: Post[], postSlug: string) => { const slug = postSlug.replace(".md", ""); - const post = getFileContentBySlug(slug); + const post = getBlogContentBySlug(slug); + + return [{ frontMatter: post.frontMatter, slug }, ...allPosts]; + }, []); +}; +export const getAllProjectsFrontMatter = (): Post[] => { + const files = fs.readdirSync(PROJECTS_PATH); + + return files.reduce((allPosts: Post[], postSlug: string) => { + const slug = postSlug.replace(".md", ""); + const post = getProjectContentBySlug(slug); return [{ frontMatter: post.frontMatter, slug }, ...allPosts]; }, []);