Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const ImageZoomOverlayContainer = ({
if (!selectedImage) return null;

return (
<div className={'zoomBox p-4 bg-white'}>
<div className={'w-full zoomBox p-4 bg-white rounded-md shadow-lg'}>
<button
onClick={() => {
setSelectedImage(null);
Expand All @@ -29,7 +29,7 @@ const ImageZoomOverlayContainer = ({
alt={'확대된 이미지'}
width={800}
height={600}
className={'rounded-none !important max-w-full max-h-[80vh]'}
className={'rounded-none !important w-full h-auto mx-auto'}
/>
</div>
);
Expand Down
8 changes: 7 additions & 1 deletion app/entities/common/Overlay/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ interface OverlayProps {
overlayOpen: boolean;
setOverlayOpen: (open: boolean) => void;
children: ReactNode;
maxWidth?: 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | number;
}
const Overlay = ({
overlayOpen = false,
setOverlayOpen,
children,
maxWidth = '2xl',
}: OverlayProps) => {
const overlayRef = useRef<HTMLDivElement>(null);
useEffect(() => {
Expand All @@ -24,13 +26,17 @@ const Overlay = ({
};
}, []);

const isMaxWidthTypeNumber = typeof maxWidth === 'number';

return (
overlayOpen && (
<div
ref={overlayRef}
className="fixed flex justify-center items-center w-screen h-screen top-0 left-0 inset-0 bg-black bg-opacity-50 z-50"
>
<div className="animate-popUp container bg-opacity-90 text-overlay rounded-lg mx-auto max-w-2xl">
<div
className={`animate-popUp container bg-opacity-90 text-overlay rounded-lg mx-auto ${isMaxWidthTypeNumber ? `max-w-[${maxWidth}px]` : `max-w-${maxWidth}`}`}
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic class name construction with template literals can lead to CSS injection vulnerabilities. Consider using a predefined map of allowed maxWidth values or sanitizing the input.

Copilot uses AI. Check for mistakes.
>
{children}
</div>
</div>
Expand Down
47 changes: 46 additions & 1 deletion app/entities/post/detail/PostBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,42 @@ const PostBody = ({ content, tags, loading }: Props) => {
}
};

const addDescriptionUnderImage = (
node: any,
index?: number,
parent?: Element
) => {
if (node.type === 'element' && node.tagName === 'img') {
const altText = node.properties.alt;
if (altText) {
const descriptionNode = {
type: 'element',
tagName: 'span',
properties: {
className: 'image-description',
},
children: [
{
type: 'text',
value: altText,
},
],
};

if (
index !== undefined &&
parent &&
parent.children &&
Array.isArray(parent.children)
) {
parent.children.splice(index + 1, 0, descriptionNode);
}
}
}

return null;
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function always returns null but is used in a visitor pattern where it should return the node or undefined. The return value should be 'node' or the function should return void.

Suggested change
return null;

Copilot uses AI. Check for mistakes.
};

const renderOpenGraph = (node: any, index?: number, parent?: Element) => {
if (node.type === 'element' && node.tagName === 'p' && node.children) {
const aTag = node.children.find(
Expand Down Expand Up @@ -226,7 +262,11 @@ const PostBody = ({ content, tags, loading }: Props) => {
</div>
) : (
<>
<Overlay overlayOpen={openImageBox} setOverlayOpen={setOpenImageBox}>
<Overlay
overlayOpen={openImageBox}
setOverlayOpen={setOpenImageBox}
maxWidth={'5xl'}
>
<ImageZoomOverlayContainer
selectedImage={selectedImage}
setSelectedImage={setSelectedImage}
Expand All @@ -253,6 +293,11 @@ const PostBody = ({ content, tags, loading }: Props) => {
parent as Element | undefined
);
addImageClickHandler(node);
addDescriptionUnderImage(
node,
index,
parent as Element | undefined
);
}}
/>
</>
Expand Down
19 changes: 18 additions & 1 deletion app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,21 @@ article.post .post-body p:has(img) {
}

article.post .post-body img {
max-width: 100%;
max-width: 90%;
height: auto;
margin: 1em 0;
border-radius: 1em;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.05);
}

article.post .post-body div > div img {
max-width: 50%;
}

article.post .post-body div > div.zoomBox img {
max-width: 100%;
}
Comment on lines +96 to +98
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CSS selector 'div > div.zoomBox img' is overly specific and tightly coupled to the HTML structure. Consider using a single class selector like '.zoomBox img' for better maintainability.

Suggested change
article.post .post-body div > div.zoomBox img {
max-width: 100%;
}

Copilot uses AI. Check for mistakes.

article.post .post-body .zoomBox img {
border-radius: 0;
}
Expand Down Expand Up @@ -175,6 +183,15 @@ article.post .post-body pre {
box-shadow: 0 0 4px rgba(0, 0, 0, 0.05);
}

article.post .image-description {
text-align: center;
font-size: 0.75em;
color: var(--text-weak);
margin-top: -0.5em;
margin-bottom: 1em;
display: block;
}

.shadow-top {
box-shadow:
0 -4px 6px -1px rgba(0, 0, 0, 0.1),
Expand Down