Conversation
Walkthrough
관련 가능성이 있는 PR
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/hooks/util/parseMarkdown.tsx`:
- Around line 46-54: The list-item formatter currently only replaces **...** and
leaves the rest unescaped, allowing raw HTML injection; create (or use) an
inline formatter that fully escapes non-bold text and only unescapes/escapes the
bold inner text via escapeHtml. Concretely, implement a helper (e.g.,
formatInline or normalizeInline) that splits content by the bold pattern, runs
escapeHtml on every non-bold chunk and for bold chunks wraps escapeHtml(inner)
in `<strong class="font-semibold">...</strong>`, then replace the current inline
replace call and the content passed to result.push(`<li...>`) with
formatInline(content); reuse the same helper for the other inline handling block
currently at lines 86-90 so both list items and the other formatter are safe.
- Around line 42-57: The global insertion of "<br/>" is bleeding into list
blocks causing "<ul><br/><li>...</li><br/></ul>"; to fix, treat list blocks as a
single flushable unit in parseMarkdown.tsx by collecting list items while inList
(the code paths that push '<ul class="my-2">' and '</ul>') and only emit the
surrounding '<ul>...</ul>' once all list items are assembled, or alternatively
prevent the global "<br/>" join from running when inList is true — update the
logic around the inList flag and the branches that push `<ul class="my-2">` /
`<li class="ml-4 list-disc">`` and the closing `</ul>` (the blocks around the
shown diff and the similar closing at lines 95-97) so that line-break insertion
is skipped for list blocks or the list is flushed as one block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 206e4c9b-e702-43a5-8f79-9016f1401ec3
📒 Files selected for processing (1)
src/hooks/util/parseMarkdown.tsx
|
코드래빗 답변 확인 부탁드립니다 @Bangdayeon |
564bf04 to
6ef06e9
Compare
|
ㅋ
코드래빗 답변 내용 해결했습니다 |
6ef06e9 to
e9fa18f
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/hooks/util/parseMarkdown.tsx (1)
10-33:⚠️ Potential issue | 🔴 Critical
formatInline가 아직 raw HTML을 그대로 통과시킵니다.일반 텍스트를
escapeHtml하지 않아<img src=x onerror=...>같은 입력이 Line 119의dangerouslySetInnerHTML까지 그대로 도달합니다. 지금 순서에서는`**x**`도%%BOLD_0%%로 깨질 수 있어서, 인라인 코드를 먼저 분리하고 나머지 텍스트만 escape한 뒤 마지막에 마크업을 복원하는 쪽이 안전합니다.🔒 제안 수정안
const formatInline = (raw: string) => { if (!raw) return ''; - - // Bold 처리 - const boldTokens: string[] = []; - const tokenized = raw.replace(/\*\*(.+?)\*\*/g, (_, g1) => { - const index = boldTokens.length; - boldTokens.push(`<strong class="font-semibold">${escapeHtml(g1)}</strong>`); - return `%%BOLD_${index}%%`; - }); - - // 인라인 코드 처리 - const inlineTokens: string[] = []; - const inlineProcessed = tokenized.replace(/`([^`]+)`/g, (_, code) => { - const index = inlineTokens.length; - inlineTokens.push(`<code class="bg-gray200 rounded px-1 text-sm">${escapeHtml(code)}</code>`); - return `%%INLINE_${index}%%`; - }); - - // placeholder 복원 - let restored = inlineProcessed.replace(/%%BOLD_(\d+)%%/g, (_, i) => boldTokens[Number(i)]); - restored = restored.replace(/%%INLINE_(\d+)%%/g, (_, i) => inlineTokens[Number(i)]); - - return restored; + return raw + .split(/(`[^`]+`)/g) + .map(part => { + const inlineMatch = part.match(/^`([^`]+)`$/); + if (inlineMatch) { + return `<code class="bg-gray200 rounded px-1 text-sm">${escapeHtml(inlineMatch[1])}</code>`; + } + + return part + .split(/(\*\*.+?\*\*)/g) + .map(chunk => { + const boldMatch = chunk.match(/^\*\*(.+?)\*\*$/); + if (boldMatch) { + return `<strong class="font-semibold">${escapeHtml(boldMatch[1])}</strong>`; + } + + return escapeHtml(chunk); + }) + .join(''); + }) + .join(''); };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/hooks/util/parseMarkdown.tsx` around lines 10 - 33, formatInline currently allows raw HTML through because bold is tokenized before the rest of the text is escaped; change the processing order in formatInline to first extract/replace inline code spans (`/`([^`]+)`/` -> inlineTokens), then escape the remaining text with escapeHtml, then tokenize/process bold markers using the escaped text (store boldTokens from escaped content), and finally restore the placeholders for bold and inline in that order so no unescaped raw HTML (e.g., <img ...>) reaches dangerouslySetInnerHTML; reference the existing symbols formatInline, inlineTokens, boldTokens, escapeHtml and the placeholder patterns %%INLINE_n%% / %%BOLD_n%% when implementing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/hooks/util/parseMarkdown.tsx`:
- Around line 10-33: formatInline currently allows raw HTML through because bold
is tokenized before the rest of the text is escaped; change the processing order
in formatInline to first extract/replace inline code spans (`/`([^`]+)`/` ->
inlineTokens), then escape the remaining text with escapeHtml, then
tokenize/process bold markers using the escaped text (store boldTokens from
escaped content), and finally restore the placeholders for bold and inline in
that order so no unescaped raw HTML (e.g., <img ...>) reaches
dangerouslySetInnerHTML; reference the existing symbols formatInline,
inlineTokens, boldTokens, escapeHtml and the placeholder patterns %%INLINE_n%% /
%%BOLD_n%% when implementing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e6e8fdc7-2ef1-4541-b4f5-e5c795d323cb
📒 Files selected for processing (1)
src/hooks/util/parseMarkdown.tsx
관련 이슈
PR 설명
<strong class="font-semibold">가 그대로 노출되는 문제 해결<strong>을 다시 escape해서 깨진 문제였고, escape를 텍스트에만 적용하도록 수정해서 해결