diff --git a/src/features/tech-log/presentation/shared/public-render/inline-renderer.tsx b/src/features/tech-log/presentation/shared/public-render/inline-renderer.tsx index 9d94a25..d6e8fd1 100644 --- a/src/features/tech-log/presentation/shared/public-render/inline-renderer.tsx +++ b/src/features/tech-log/presentation/shared/public-render/inline-renderer.tsx @@ -8,10 +8,35 @@ function assertNever(value: never): never { throw new Error(`Unsupported inline value: ${JSON.stringify(value)}`); } +/** + * 문단 안의 줄바꿈을 그대로 보여준다. + * + *

Markdown 은 한 번의 줄바꿈을 문단을 잇는 공백으로 읽는다. 파서는 그 줄바꿈을 텍스트에 + * 남겨 두는데, 여기서 그대로 내보내면 HTML 이 다시 공백으로 접는다 — 작성자가 엔터로 나눠 쓴 + * 글이 한 줄로 이어져 보였다. 미리보기만의 현상이 아니었다: 공개 화면도 같은 렌더러를 쓴다. + * + *

빈 줄로 나눈 문단은 파서가 이미 문단 둘로 만들어 두므로 여기 오지 않는다. 이 함수가 보는 + * 것은 한 문단 안의 줄바꿈뿐이고, 작성자가 의도한 것도 그것이다. + */ +function renderText(text: string, key: number) { + const lines = text.split("\n"); + if (lines.length === 1) return {text}; + return ( + + {lines.map((line, index) => ( + + {index > 0 ?
: null} + {line} +
+ ))} +
+ ); +} + function renderInline(inline: Inline, key: number) { switch (inline.type) { case "TEXT": - return {inline.text}; + return renderText(inline.text, key); case "INLINE_CODE": return {inline.code}; case "EMPHASIS": diff --git a/tests/component/inline-line-breaks.test.tsx b/tests/component/inline-line-breaks.test.tsx new file mode 100644 index 0000000..c7e2797 --- /dev/null +++ b/tests/component/inline-line-breaks.test.tsx @@ -0,0 +1,36 @@ +// @vitest-environment jsdom + +import { render } from "@testing-library/react"; +import { describe, expect, it } from "vitest"; + +import { InlineRenderer } from "../../src/features/tech-log/presentation/shared/public-render/inline-renderer.tsx"; + +/** + * 작성자가 엔터로 나눠 쓴 글이 한 줄로 이어져 보였다. Markdown 이 한 번의 줄바꿈을 문단 내 공백으로 + * 읽고, 파서가 그 줄바꿈을 텍스트에 남긴 뒤, HTML 이 다시 공백으로 접기 때문이다. 미리보기와 공개 + * 화면이 같은 렌더러를 쓰므로 두 곳 모두에서 그랬다. + */ +describe("문단 안의 줄바꿈", () => { + it("줄바꿈을
로 그린다", () => { + const { container } = render( + , + ); + expect(container.querySelectorAll("br")).toHaveLength(1); + expect(container.textContent).toBe("첫째 줄둘째 줄"); + }); + + it("줄바꿈이 없으면
를 넣지 않는다", () => { + const { container } = render( + , + ); + expect(container.querySelectorAll("br")).toHaveLength(0); + expect(container.textContent).toBe("한 줄"); + }); + + it("여러 번 엔터를 친 만큼 내려간다", () => { + const { container } = render( + , + ); + expect(container.querySelectorAll("br")).toHaveLength(2); + }); +});