Skip to content

Commit

Permalink
Merge pull request #231 from 1chooo/feature/#218
Browse files Browse the repository at this point in the history
feat(markdown): update image tag
  • Loading branch information
1chooo authored Sep 11, 2024
2 parents cbdb767 + c09b119 commit 5c12d22
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 4 deletions.
43 changes: 43 additions & 0 deletions apps/docs/pages/wiki.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,46 @@ $ npm install next
- [How to Migrate from create-react-app to Vite using Jest and Browserslist](https://www.freecodecamp.org/news/how-to-migrate-from-create-react-app-to-vite/)
- [Migrating from Create React App](https://nextjs-ja-translation-docs.vercel.app/docs/migrating/from-create-react-app)

# Dangerously Set innerHTML

https://dev.to/shareef/rendering-markdown-made-easy-with-react-markdown-in-reactjs-and-nextjs-web-apps-259d

```
In HTML, <div> cannot be a descendant of <p>.
This will cause a hydration error.
```

```tsx
...
<Markdown>
<p>
^^^
<http://localhost:3000/_next/static/chunks/src_dd03ef._.js:150:225>
<div>
```

```diff
+ const isImageNode = (node: any): node is Element => {
+ return node && node.type === 'element' && node.tagName === 'img';
+ };

const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content }) => (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]}
components={{
+ p: ({ node, children }) => {
+ const hasImage = node && node.children && node.children.some(isImageNode);
+ if (hasImage) {
+ return <>{children}</>;
+ }
+ return <p>{children}</p>;
+ },
...
>
{content}
</ReactMarkdown>
);

export default MarkdownRenderer;
```
4 changes: 2 additions & 2 deletions apps/web/src/app/post/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import Link from 'next/link';
import { getBlogPosts } from '../db/blog';
import { getBlogPosts } from '@/app/db/blog';
import PageHeader from '@/components/page-header';
import Image from 'next/image';

export const metadata = {
title: 'Blog',
title: 'Blog | Hugo ChunHo Lin (1chooo) | Open Source Enthusiast',
description: 'Read my thoughts on software development, design, and more.',
};

Expand Down
55 changes: 55 additions & 0 deletions apps/web/src/components/markdown/markdown-image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"use client";

import React, { useState } from 'react';
import Image from 'next/image';

interface MarkdownImageProps {
src: string;
alt?: string;
}

const MarkdownImage: React.FC<MarkdownImageProps> = ({ src, alt }) => {
const [imageSize, setImageSize] = useState({ width: 1, height: 1 });

return (
<div
style={{
marginTop: '1rem',
maxWidth: '80%',
margin: '0 auto',
textAlign: 'center',
}}
>
<Image
src={src}
alt={alt ?? 'Image'}
layout="responsive"
objectFit="contain"
priority={true}
onLoadingComplete={(target) => {
setImageSize({
width: target.naturalWidth,
height: target.naturalHeight,
});
}}
width={imageSize.width}
height={imageSize.height}
/>
{alt && (
<div
style={{
marginTop: '0.5rem',
fontSize: '0.9rem',
color: '#555',
textAlign: 'center',
marginBottom: '1rem',
}}
>
{alt}
</div>
)}
</div>
);
};

export default MarkdownImage;
15 changes: 13 additions & 2 deletions apps/web/src/components/markdown/markdown-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,32 @@ import rehypeRaw from 'rehype-raw';
import Anchor from './anchor';
import BlockQuote from './block-quote';
import CodeBlock from './code-block';

import MarkdownImage from './markdown-image';

interface MarkdownRendererProps {
content: string;
}

const isImageNode = (node: any): node is Element => {
return node && node.type === 'element' && node.tagName === 'img';
};

const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content }) => (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]}
components={{
p: ({ node, children }) => {
const hasImage = node && node.children && node.children.some(isImageNode);
if (hasImage) {
return <>{children}</>;
}
return <p>{children}</p>;
},
a: (props) => <Anchor {...props} />,
sup: 'sup',
sub: 'sub',
img: (props) => <img {...props} style={{ maxWidth: '80%', margin: '0 auto' }} />,
img: (props) => <MarkdownImage src={props.src ?? ''} alt={props.alt} />,
ul: (props) => (
<ul
{...props}
Expand Down

0 comments on commit 5c12d22

Please sign in to comment.