Skip to content

Commit

Permalink
Merge pull request #4 from zhumeisongsong/feature/render-markdown
Browse files Browse the repository at this point in the history
✨ Render markdown with mermaid graph
  • Loading branch information
zhumeisongsong authored Oct 7, 2024
2 parents 5d8b112 + 5ea6399 commit a85aacb
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 34 deletions.
33 changes: 30 additions & 3 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
name: Release
# Sample workflow for building and deploying a Next.js site to GitHub Pages
#
# To get started with Next.js see: https://nextjs.org/docs/getting-started
#
name: Deploy Next.js site to Pages

on:
# Runs on pushes targeting the default branch
push:
branches:
- main
branches: ["main"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write

# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false

jobs:
setup:
Expand All @@ -14,3 +33,11 @@ jobs:
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-semantic-release.yml@main
secrets:
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}

build:
needs: [lint, type-check]
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-nextjs-build-github-pages.yml@main

deploy:
needs: build
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-nextjs-deploy-github-pages.yml@main
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: CI

on:
pull_request:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

jobs:
setup:
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-pnpm-setup.yml@main

lint:
needs: setup
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-eslint.yml@main

type-check:
needs: setup
uses: zhumeisongsong/shared-actions/.github/workflows/reusable-ts-type-check.yml@main

1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"cSpell.words": [
"dompurify",
"Nextjs"
]
}
4 changes: 2 additions & 2 deletions _posts/2024-08-29-DDD.md → _posts/2024-08-29-DDD-1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: "Domain-Driven Design"
title: "Domain-Driven Design 1"
excerpt: ""
coverImage: "/blog/assets/ddd-cover.jpg"
date: "2024-08-29"
Expand All @@ -24,7 +24,7 @@ Given a deadline, as long as in this deadline before the completion of the requi
- Lack of process management
- Only the pursuit of short-term business goals

As a result, the corresponding code may be a lumpy mess that is difficult to extend and maintain, laying a huge technical pit for the future.
As a result, the corresponding code may be `a lumpy mess` that is difficult to extend and maintain, laying a huge technical pit for the future.

### Data-driven design

Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"classnames": "^2.5.1",
"date-fns": "^3.6.0",
"dompurify": "^3.1.7",
"gray-matter": "^4.0.3",
"mermaid": "^11.3.0",
"next": "latest",
Expand All @@ -22,6 +23,7 @@
"remark-html": "^16.0.1"
},
"devDependencies": {
"@types/dompurify": "^3.0.5",
"@types/node": "^20.14.8",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
Expand Down
23 changes: 23 additions & 0 deletions pnpm-lock.yaml

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

26 changes: 26 additions & 0 deletions src/app/_components/body-markdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client";
import markdownToHtml from "@/lib/markdown-to-html";
import { useEffect, useState } from "react";
import DOMPurify from 'dompurify';

import markdownStyles from "./markdown-styles.module.css";

type Props = {
content: string;
};

export function BodyMarkdown({ content }: Props) {
const [html, setHtml] = useState<string>("");
useEffect(() => {
markdownToHtml(content).then((html) => {
setHtml(html);
});
}, [content]);

return (
<div
className={markdownStyles["markdown"]}
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }}
/>
);
}
35 changes: 35 additions & 0 deletions src/app/_components/body-mermaid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client";
import mermaid from "mermaid";
import { useEffect, useRef } from "react";

import mermaidStyles from "./mermaid-styles.module.css";

type Props = {
graph: string;
};

export function BodyMermaid({ graph }: Props) {
const chartRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (chartRef.current) {
try {
mermaid.contentLoaded();
} catch (error) {
console.error("Error rendering mermaid diagram:", error);
// Optionally, you could set an error state here and render an error message
}
}
}, [graph]);

// Basic validation
if (!graph || typeof graph !== "string") {
return <div>Invalid graph data</div>;
}

return (
<div ref={chartRef} className={mermaidStyles["mermaid"]}>
<div className="mermaid">{graph}</div>
</div>
);
}
10 changes: 10 additions & 0 deletions src/app/_components/markdown-styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@
@apply text-sky-500 underline;
}

.markdown ul {
list-style: disc;
margin-left: 32px;
}

.markdown code {
@apply bg-orange-200 text-black;
}


3 changes: 3 additions & 0 deletions src/app/_components/mermaid-styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.mermaid {
text-align: center;
}
45 changes: 18 additions & 27 deletions src/app/_components/post-body.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,34 @@
"use client";

import { useEffect, useRef } from "react";
import mermaid from "mermaid";
import markdownStyles from "./markdown-styles.module.css";
import { BodyMarkdown } from "@/app/_components/body-markdown";
import { BodyMermaid } from "@/app/_components/body-mermaid";

type Props = {
content: string;
};

const isMermaidGraph = (content: string) => {
const mermaidKeywords = [
"graph",
"flowchart",
"sequenceDiagram",
"classDiagram",
"stateDiagram",
"erDiagram",
"journey",
];
return mermaidKeywords.some((keyword) => content.trim().startsWith(keyword));
};

export function PostBody({ content }: Props) {
const chartRef = useRef(null);
const array = content.split("```");

useEffect(() => {
array.map((item, index) => {
if (item.indexOf("graph") > -1 && chartRef.current) {
console.log(item);
mermaid.contentLoaded(); // Rerenders any existing mermaid diagrams
}
});
}, [array]);

return (
<div className="max-w-2xl mx-auto">
{array.map((item, index) => {
if (item.indexOf("graph") > -1) {
return (
<div ref={chartRef} key={index} className="mermaid">
{item}
</div>
);
if (isMermaidGraph(item)) {
return <BodyMermaid key={index} graph={item} />;
}
return (
<div
key={index}
className={markdownStyles["markdown"]}
dangerouslySetInnerHTML={{ __html: item }}
/>
);
return <BodyMarkdown key={index} content={item} />;
})}
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/lib/markdown-to-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import remarkGfm from "remark-gfm";

export default async function markdownToHtml(markdown: string) {
const result = await remark()
// .use(remarkGfm)
// .use(remarkHtml)
.use(remarkGfm)
.use(remarkHtml)
.process(markdown);

return result.toString();
Expand Down

0 comments on commit a85aacb

Please sign in to comment.