Skip to content

Commit

Permalink
Added in markdown parser.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisForti committed Sep 7, 2024
1 parent 8eec636 commit 1293c6c
Show file tree
Hide file tree
Showing 19 changed files with 470 additions and 75 deletions.
25 changes: 25 additions & 0 deletions content/chris.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Understanding TypeScript
published: true
description: A comprehensive guide to TypeScript.
date: 2024-03-04
slug: understanding-typescript
tags:
- typescript
- programming
imageUrl: "/Chris.png"
---

# Content

## Introduction

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla blandit aliquam finibus.

## Main Content

Detailed content goes here. Include sections, lists, code snippets, images, tables, etc.

### Subsection

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus
62 changes: 62 additions & 0 deletions content/example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
published: true
title: Example
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla blandit aliquam finibus. Sed venenatis placerat eros, eget pulvinar lacus elementum ut. In hac habitasse platea dictumst. Etiam sed erat quis odio vehicula consequat. Phasellus magna magna, dignissim at felis eu, pulvinar venenatis turpis. Sed molestie consectetur magna, eget aliquam erat fermentum at. Nam bibendum enim in quam consequat, ut ultricies orci pellentesque. Curabitur viverra, est efficitur cursus cursus, ante magna eleifend sapien, eget pellentesque eros erat sit amet ante. Integer volutpat hendrerit imperdiet. Nulla facilisi. Quisque laoreet sem dolor, sed porttitor turpis pulvinar quis.
date: 2023-03-04
slug: example
---

# Example

This is an example post.
Here is some code:

```js
const helloWorld = "Hello, World!";

console.log(helloWorld);
```

## Example 2

This is an example `of a inline code block`.

### Example 3

This is an example of a list:

- Item 1
- Nested Item 1
- Nested Item 2
- Item 2
- Nested Item 1
- Deeply Nested Item 1
- Item 3

#### Example 4

This is an example of a numbered list:

1. Item 1
1. Nested Item 1
2. Nested Item 2
2. Item 2
1. Nested Item 1
1. Deeply Nested Item 1
3. Item 3

##### Example 5

This is an example of a table:

| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------- |
| Row 1 | Row 1 | Row 1 |
| Row 2 | Row 2 | Row 2 |
| Row 3 | Row 3 | Row 3 |

###### Example 6

This is an example of a blockquote:

> This is a blockquote.
23 changes: 23 additions & 0 deletions content/test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
published: true
title: Test
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla blandit aliquam finibus. Sed venenatis placerat eros, eget pulvinar lacus elementum ut. In hac habitasse platea dictumst. Etiam sed erat quis odio vehicula consequat. Phasellus magna magna, dignissim at felis eu, pulvinar venenatis turpis. Sed molestie consectetur magna, eget aliquam erat fermentum at. Nam bibendum enim in quam consequat, ut ultricies orci pellentesque. Curabitur viverra, est efficitur cursus cursus, ante magna eleifend sapien, eget pellentesque eros erat sit amet ante. Integer volutpat hendrerit imperdiet. Nulla facilisi. Quisque laoreet sem dolor, sed porttitor turpis pulvinar quis.
date: 2023-03-04
slug: test
---

# Test File

This is an test post.

## Some Content

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla blandit aliquam finibus. Sed venenatis placerat eros, eget pulvinar lacus elementum ut. In hac habitasse platea dictumst. Etiam sed erat quis odio vehicula consequat. Phasellus magna magna, dignissim at felis eu, pulvinar venenatis turpis. Sed molestie consectetur magna, eget aliquam erat fermentum at. Nam bibendum enim in quam consequat, ut ultricies orci pellentesque. Curabitur viverra, est efficitur cursus cursus, ante magna eleifend sapien, eget pellentesque eros erat sit amet ante. Integer volutpat hendrerit imperdiet. Nulla facilisi. Quisque laoreet sem dolor, sed porttitor turpis pulvinar quis.

Nullam sodales scelerisque ornare. Integer sed lorem sed purus dignissim egestas. Mauris rhoncus tellus nisl, eu posuere diam hendrerit eu. Nulla scelerisque dolor lacus, ac vestibulum lacus tristique eget. Quisque tempor, lorem sed viverra tincidunt, eros velit efficitur neque, in iaculis ipsum libero eget nisl. Nunc a ipsum sed tellus volutpat accumsan. Duis sodales risus luctus velit iaculis pretium. Pellentesque tincidunt lobortis laoreet. Nam imperdiet, risus rutrum luctus consectetur, dui justo venenatis turpis, nec vestibulum tortor magna vel leo. Morbi blandit felis eget velit mollis, sagittis interdum velit porta. Vivamus tincidunt gravida facilisis. Integer condimentum, augue vel tristique tempor, lorem ipsum convallis mi, sit amet ultricies lectus nunc in orci. Pellentesque vel magna tellus.

Cras ullamcorper felis vel nisi tempor commodo. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque ac augue faucibus, fermentum nisl nec, fermentum massa. Proin sit amet venenatis ligula, at pulvinar velit. Nunc auctor metus in urna placerat euismod. Quisque blandit turpis lacus, posuere vehicula erat cursus vel. Donec faucibus, ex eget tempus egestas, nibh mauris pellentesque tortor, malesuada posuere lorem elit tristique quam. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Pellentesque ut neque eu tellus euismod volutpat. Pellentesque maximus est leo, id finibus enim vehicula in.

Proin a enim at lorem maximus semper vel non mauris. Cras non pulvinar nunc. Proin tincidunt tempus purus, sed congue sem ultrices vel. Vestibulum justo justo, vestibulum nec scelerisque et, egestas eget felis. Sed pulvinar in massa vel tincidunt. Duis ac quam a diam gravida convallis. Nam dapibus velit a augue rhoncus, eu consectetur nulla efficitur. Aliquam vitae dolor imperdiet, ultricies ligula nec, euismod enim. Cras vehicula est vitae justo dignissim mattis. Praesent eleifend ullamcorper cursus.

In eget rhoncus lacus. Maecenas semper iaculis pharetra. Duis auctor purus sed ligula viverra iaculis. Vivamus congue semper porta. Donec nec nunc vitae massa tempus rhoncus vel in orci. Curabitur sollicitudin enim sed elit semper maximus eu non purus. Nulla sagittis odio orci, non congue nulla faucibus ac. Nam vel pharetra turpis. Proin sed euismod tortor. Suspendisse auctor erat eu lectus vestibulum accumsan. Phasellus dictum condimentum ligula a ornare. Mauris condimentum malesuada nibh, commodo iaculis nisi dignissim et. Donec vestibulum turpis nibh, vitae dapibus dui gravida ac. Nam malesuada nulla nec ex congue rutrum. Integer non varius risus.
75 changes: 75 additions & 0 deletions content/with-image.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
published: true
title: With Image
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla blandit aliquam finibus. Sed venenatis placerat eros, eget pulvinar lacus elementum ut. In hac habitasse platea dictumst. Etiam sed erat quis odio vehicula consequat. Phasellus magna magna, dignissim at felis eu, pulvinar venenatis turpis. Sed molestie consectetur magna, eget aliquam erat fermentum at. Nam bibendum enim in quam consequat, ut ultricies orci pellentesque. Curabitur viverra, est efficitur cursus cursus, ante magna eleifend sapien, eget pellentesque eros erat sit amet ante. Integer volutpat hendrerit imperdiet. Nulla facilisi. Quisque laoreet sem dolor, sed porttitor turpis pulvinar quis.
date: 2024-03-04
imageUrl: https://images.unsplash.com/photo-1517841905240-472988babdf9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80
slug: with-image
---

# Example

This is an example post.
Here is some prose:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus elementum tempus scelerisque. Aliquam mattis placerat quam id gravida. Nam nibh mi, dignissim a feugiat vitae, placerat non ipsum. Cras in libero sit amet erat ornare lobortis. Curabitur elementum tortor eros, vitae aliquet turpis rutrum quis. Curabitur ut interdum elit. In viverra finibus nisi, id vehicula mi pellentesque a. Vestibulum gravida magna odio, at cursus elit sagittis non.

Morbi sagittis in velit non porttitor. Nam ac lobortis dolor, ultrices laoreet magna. Nulla at rhoncus ligula, eu convallis libero. Curabitur placerat ante eu ex accumsan blandit. Suspendisse vel volutpat nunc, eu sagittis felis. Nam quis elementum lorem. Sed tristique ultrices nisi, id tincidunt urna bibendum vel. Nam imperdiet accumsan libero, ut viverra dolor laoreet eu. Praesent aliquet lacus quis nisl iaculis hendrerit. Sed in semper ligula. Ut ultricies non arcu quis maximus. Mauris facilisis mi rhoncus porta faucibus. Quisque interdum, ante ac sollicitudin scelerisque, metus diam varius nisl, sit amet pretium lacus turpis ut tellus. Praesent et quam ullamcorper, gravida ligula in, placerat leo. Sed pharetra porttitor velit, a molestie justo facilisis quis.

Donec non feugiat quam. Suspendisse potenti. Sed eu molestie nisl. Aliquam vel nulla malesuada, scelerisque turpis id, fermentum felis. In accumsan, massa sit amet auctor varius, quam nisl ullamcorper neque, tempus congue mauris mauris quis velit. Donec in faucibus mauris, id cursus elit. Maecenas eget lacus massa. Mauris euismod pretium lacus nec malesuada. Donec aliquet ipsum et justo euismod commodo. Duis commodo sed velit sit amet dapibus. Duis pulvinar ut nulla at faucibus. Duis ut metus vitae orci suscipit sodales vel sit amet enim.

Nam ipsum urna, blandit non odio ut, pellentesque rutrum felis. Donec pulvinar, mi non dictum pretium, metus arcu sodales neque, at efficitur ligula diam a lectus. Vivamus malesuada arcu arcu, nec sodales nibh molestie eget. Praesent vel elit sed turpis tempor fermentum at eu lorem. Proin lacinia risus nec risus fringilla, sed vulputate purus pulvinar. Donec id eleifend felis. Phasellus bibendum nisi et purus volutpat, sit amet tempor quam dictum. Vivamus a urna vel leo fringilla ullamcorper sed at eros. Aliquam leo leo, molestie nec massa ut, aliquet tempus neque.

Morbi eros ipsum, condimentum id placerat vitae, aliquet sit amet purus. Curabitur tempor non mi id posuere. Pellentesque vitae arcu nisi. Aenean tortor tellus, fermentum nec ante at, euismod dictum diam. In sed justo et mi dignissim interdum. Donec ante dui, suscipit in nisi non, sodales dictum augue. Sed sit amet nisl in nisl pharetra interdum at quis nisl. Sed iaculis ligula eu sodales tincidunt. Morbi tristique placerat sapien et sagittis. Sed accumsan libero ac tincidunt venenatis. Nulla in mi risus. Sed odio ante, pulvinar a sem et, commodo scelerisque leo. Morbi eget ipsum nisl. Nunc tristique enim eu ex convallis lobortis.

Here is some code:

```js
const helloWorld = "Hello, World!";

console.log(helloWorld);
```

## Example 2

This is an example `of a inline code block`.

### Example 3

This is an example of a list:

- Item 1
- Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Nested Item 2, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Item 2
- Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Deeply Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Item 3

#### Example 4

This is an example of a numbered list:

1. Item 1
1. Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
2. Nested Item 2, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
2. Item 2
1. Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
1. Deeply Nested Item 1, Lorem ipsum dolor sit amet, consectetur adipiscing elit.
3. Item 3

##### Example 5

This is an example of a table:

| First Header | Second Header | Third Header |
| ------------ | -------------------------------------------------------- | -------------------------------------------------------- |
| First Row | Lorem ipsum dolor sit amet, consectetur adipiscing elit. | Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
| Second Row | Lorem ipsum dolor sit amet, consectetur adipiscing elit. | Lorem ipsum dolor sit amet, consectetur adipiscing elit. |
| Third Row | Lorem ipsum dolor sit amet, consectetur adipiscing elit. | Lorem ipsum dolor sit amet, consectetur adipiscing elit. |

###### Example 6

This is an example of a blockquote:

> This is a blockquote.
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"marked": "^14.1.1",
"parse-md": "^3.0.3",
"postcss": "^8.4.38",
"prettier": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.5",
Expand Down
139 changes: 139 additions & 0 deletions parse-markdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { readFileSync, readdirSync, writeFileSync } from "fs";
import splitMetadataFromMDContent from "parse-md";
import { Marked } from "marked";
import { v4 as uuidv4 } from "uuid";
import { Plugin } from "vite";

type Metadata = {
published: boolean;
title: string;
description: string;
date: Date;
slug: string;
tags?: string[];
imageUrl?: string;
};

type Post = {
id: string;
metadata: Metadata;
html: string;
};

export function buildPostsFromMarkdown(): Plugin {
return {
name: "posts_builder",
buildStart() {
process.stdout.write("Building posts.json file...\n");
createPostsJson();
},
handleHotUpdate(ctx) {
if (ctx.file.includes("content")) {
createPostsJson();
}
},
};
}

function createPostsJson() {
try {
const files = readdirSync("./content").filter((file) =>
file.endsWith(".md"),
);
const output: Post[] = [];
files.forEach((file) => {
const post = parseMarkdownFile(`./content/${file}`);
if (!post) {
console.log("\x1b[34mError in " + file + ", skipping \x1b[0m");
return null;
}
output.push(post);
});
writeFileSync("./src/posts/posts.json", JSON.stringify(output, null, 2));
} catch (error) {
console.error(error);
}
}

function parseMarkdownFile(filePath: string) {
const myFile = readFileSync(filePath, "utf-8");
const { metadata, content } = splitMetadataFromMDContent(myFile) as {
metadata: Metadata;
content: string;
};
const fileName = filePath.split("/").pop();
if (!fileName) {
console.error(" \x1b[33mBad path: ", filePath, " \x1b[0m");
return null;
}
if (!validateMetadata(metadata, fileName)) {
console.error(" \x1b[33minvalid metadata in", fileName, " \x1b[0m");
return null;
}

const marked = new Marked();
const html = marked.parse(content);

const output = {
id: uuidv4(),
metadata,
html,
};
return output as Post;
}

function validateMetadata(metadata: unknown, fileName: string) {
if (typeof metadata != "object" || metadata === null) {
return false;
}

const { published, title, description, date, slug, tags, imageUrl } =

Check failure on line 90 in parse-markdown.ts

View workflow job for this annotation

GitHub Actions / Lint

'tags' is assigned a value but never used
metadata as Metadata;
try {
if (typeof published !== "boolean") {
throw new Error(
"\x1b[31mThe markdown must contain a published boolean. \x1b[0m",
);
}
if (typeof title !== "string") {
throw new Error(
"\x1b[31mThe markdown must contain a valid title string. \x1b[0m",
);
}
if (typeof description !== "string") {
throw new Error(
"\x1b[31mThe markdown must contain a valid description string. \x1b[0m",
);
}
if (!(date instanceof Date)) {
throw new Error(
"\x1b[31mThe markdown must contain a valid date object. \x1b[0m",
);
}
if (typeof slug !== "string") {
throw new Error(
"\x1b[31mThe markdown must contain a valid slug string. \x1b[0m",
);
}
if (
imageUrl &&
!imageUrl.startsWith("http://") &&
!imageUrl.startsWith("https://") &&
!imageUrl.startsWith("/")
) {
throw new Error(
"\x1b[31mimageUrl must be an absolute URL or a path starting with /\nExample: /images/my-image.jpg for image in public folder\nOr: https://example.com/image.jpg for an external image\x1b[0m",
);
}
} catch (error) {
if ("message" in (error as Error)) {
console.error(
"\x1b[34mThere was an error inside of " + fileName + ":\n\x1b[0m",
// @ts-expect-error

Check failure on line 132 in parse-markdown.ts

View workflow job for this annotation

GitHub Actions / Lint

Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer
error.message,
);
}
return false;
}
return true;
}
File renamed without changes
File renamed without changes
File renamed without changes
Loading

0 comments on commit 1293c6c

Please sign in to comment.