Skip to content

Commit 19496dc

Browse files
fix(markdown): insert spaces around ** for CommonMark flanking fix
Replace <strong> HTML conversion and punctuation-moving approaches with space insertion. When left/right-flanking rules would fail, insert a space before/after ** so the delimiter is adjacent to whitespace, satisfying flanking conditions without altering bold content or requiring rehype-raw. Also preserve meaningful trailing spaces when trimming inner bold content (step 1), and remove rehype-raw devDependency. Generated with oh-my-agent Co-Authored-By: First Fluke <our.first.fluke@gmail.com>
1 parent aaeaf17 commit 19496dc

4 files changed

Lines changed: 130 additions & 103 deletions

File tree

bun.lock

Lines changed: 1 addition & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,99 @@
11
import React from "react";
22
import { renderToStaticMarkup } from "react-dom/server";
33
import Markdown from "react-markdown";
4-
import rehypeRaw from "rehype-raw";
54
import { describe, expect, it } from "vitest";
65
import { preprocessMarkdown } from "@/preprocess";
76

87
function renderMarkdown(markdown: string): string {
9-
return renderToStaticMarkup(
10-
React.createElement(Markdown, { rehypePlugins: [rehypeRaw] }, markdown),
11-
);
8+
return renderToStaticMarkup(React.createElement(Markdown, null, markdown));
129
}
1310

1411
describe("preprocessMarkdown integration", () => {
15-
it("renders bold Korean text with verb endings as strong tags", () => {
12+
// --- Basic bold rendering ---
13+
14+
it("renders bold Korean text with verb endings", () => {
1615
const input = "**앱 권한을 다시 승인**해 주시거나, **앱을 재설치**해 주셔야 합니다.";
1716

1817
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
1918
"<p><strong>앱 권한을 다시 승인</strong>해 주시거나, <strong>앱을 재설치</strong>해 주셔야 합니다.</p>",
2019
);
2120
});
2221

23-
it("renders quoted bold product names before Korean particles as strong tags", () => {
22+
it("renders bold text followed by Korean without punct boundary", () => {
23+
expect(renderMarkdown(preprocessMarkdown("**볼드텍스트**입니다"))).toBe(
24+
"<p><strong>볼드텍스트</strong>입니다</p>",
25+
);
26+
});
27+
28+
// --- Quote handling ---
29+
30+
it("renders quoted bold product names before Korean particles", () => {
2431
const input = "**'액티브핏 데일리 그린 파우더'**에 [BEST] 표시를 완료했습니다!";
2532

2633
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
2734
"<p>&#x27;<strong>액티브핏 데일리 그린 파우더</strong>&#x27;에 [BEST] 표시를 완료했습니다!</p>",
2835
);
2936
});
3037

31-
it("keeps quoted bold text inside strong tags when punctuation follows", () => {
38+
it("renders quoted bold text before punctuation", () => {
3239
const input = "**'상품명 변경'**: 상품 이름";
3340

3441
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
3542
"<p><strong>&#x27;상품명 변경&#x27;</strong>: 상품 이름</p>",
3643
);
3744
});
3845

39-
it("renders bold with closing paren before Korean as strong (paren inside)", () => {
46+
// --- Closing punct + Korean/digit (right-flanking fix) ---
47+
48+
it("renders bold with closing paren before Korean", () => {
4049
const input = "**바꾸고 싶은 부분(색상, 레이아웃, 문구 등)**을 말씀해 주시면";
4150

4251
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
43-
"<p><strong>바꾸고 싶은 부분(색상, 레이아웃, 문구 등)</strong>을 말씀해 주시면</p>",
52+
"<p><strong>바꾸고 싶은 부분(색상, 레이아웃, 문구 등)</strong> 을 말씀해 주시면</p>",
4453
);
4554
});
4655

47-
it("renders bold with brackets inside strong when preceded by Korean", () => {
48-
const input = "관리자 화면에서**[디자인 관리 > 디자인 보관함]**에 있는 스킨";
56+
it("renders bold with closing bracket before Korean", () => {
57+
const input = "관리자 페이지의 **[설정 > 일반]**에서 변경할 수 있습니다.";
4958

5059
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
51-
"<p>관리자 화면에서<strong>[디자인 관리 &gt; 디자인 보관함]</strong>에 있는 스킨</p>",
60+
"<p>관리자 페이지의 <strong>[설정 &gt; 일반]</strong> 에서 변경할 수 있습니다.</p>",
5261
);
5362
});
5463

55-
it("renders bold with brackets inside strong when preceded by space", () => {
56-
const input = "관리자 페이지의 **[설정 > 일반]**에서 변경할 수 있습니다.";
57-
58-
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
59-
"<p>관리자 페이지의 <strong>[설정 &gt; 일반]</strong>에서 변경할 수 있습니다.</p>",
64+
it("renders bold with closing colon before Korean", () => {
65+
expect(renderMarkdown(preprocessMarkdown("**주의:**사항을 확인하세요"))).toBe(
66+
"<p><strong>주의:</strong> 사항을 확인하세요</p>",
6067
);
6168
});
6269

63-
it("renders bold with trailing colon before Korean as strong", () => {
64-
const input = "**주의:**사항을 확인하세요";
70+
it("renders bold with closing colon before digit", () => {
71+
const input = "**보강된 주요 속성:**1. 할인 효과 적용";
6572

6673
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
67-
"<p><strong>주의:</strong>사항을 확인하세요</p>",
74+
"<p><strong>보강된 주요 속성:</strong> 1. 할인 효과 적용</p>",
6875
);
6976
});
7077

71-
it("renders bold with trailing colon before digit as strong", () => {
72-
const input =
73-
"**보강된 주요 속성:**1. 할인 효과 적용 (심리적 가격): - 기존에는 판매가(15,000원)만 있었으나";
78+
// --- Opening punct + Korean before (left-flanking fix) ---
79+
80+
it("renders bold with brackets when preceded by Korean", () => {
81+
const input = "관리자 화면에서**[디자인 관리 > 디자인 보관함]**에 있는 스킨";
7482

7583
expect(renderMarkdown(preprocessMarkdown(input))).toBe(
76-
"<p><strong>보강된 주요 속성:</strong>1. 할인 효과 적용 (심리적 가격): - 기존에는 판매가(15,000원)만 있었으나</p>",
84+
"<p>관리자 화면에서 <strong>[디자인 관리 &gt; 디자인 보관함]</strong> 에 있는 스킨</p>",
85+
);
86+
});
87+
88+
it("renders bold with parens when preceded by Korean", () => {
89+
expect(renderMarkdown(preprocessMarkdown("결제에서**(할인 적용)**을 확인"))).toBe(
90+
"<p>결제에서 <strong>(할인 적용)</strong> 을 확인</p>",
7791
);
7892
});
7993

80-
it("renders bold correctly when space is trimmed before closing markers", () => {
94+
// --- Space trimming + flanking fix combined ---
95+
96+
it("renders bold after trimming trailing space", () => {
8197
const input =
8298
"**다른 디자인의 스타일을 수정하거나, 현재 디자인의 느낌을 완전히 바꿔볼까요? ** 원하시는 작업이 있다면 말씀해 주세요!";
8399

@@ -86,12 +102,18 @@ describe("preprocessMarkdown integration", () => {
86102
);
87103
});
88104

89-
it("renders multiple broken bold segments correctly with preserved spacing", () => {
105+
it("renders multiple broken bold segments with preserved spacing", () => {
90106
const input =
91107
"**단 한 줄도 수정되지 않았습니다. **시도했던 과정에서 코드에는**아무런 변화가 생기지 않았으니 안심하셔도 됩니다. **";
92-
93108
const result = renderMarkdown(preprocessMarkdown(input));
109+
94110
expect(result).toContain("<strong>단 한 줄도 수정되지 않았습니다.</strong>");
95111
expect(result).toContain("<strong>아무런 변화가 생기지 않았으니 안심하셔도 됩니다.</strong>");
96112
});
113+
114+
it("renders bold with trimmed space and closing paren before Korean", () => {
115+
expect(renderMarkdown(preprocessMarkdown("**쇼핑몰 기본디자인 (base) **입니다"))).toBe(
116+
"<p><strong>쇼핑몰 기본디자인 (base)</strong> 입니다</p>",
117+
);
118+
});
97119
});

0 commit comments

Comments
 (0)