diff --git a/app/modules/cafe24/store.py b/app/modules/cafe24/store.py
index a12eeec..e4fdc80 100644
--- a/app/modules/cafe24/store.py
+++ b/app/modules/cafe24/store.py
@@ -241,12 +241,29 @@ def _format_html(source: str, indent: str) -> str:
return indent * min(max(level, 0), _MAX_INDENT)
def flush() -> None:
- """모아둔 인라인/텍스트를 한 줄로 내보낸다(빈 줄은 버린다)."""
+ """모아둔 인라인/텍스트를 내보낸다.
+
+ 원문에 이미 있던 줄바꿈은 **그대로 살린다.** 이미지가 한 줄에 하나씩 적혀
+ 있으면 그 모양이 저자의 의도이고, 한 줄로 합치면 오히려 읽기 어려워진다.
+ 각 줄마다 현재 깊이로 들여쓴다(줄 앞 공백은 렌더링에 영향이 없다).
+ 빈 줄은 연속 한 개까지만 남겨 구획을 유지한다.
+ """
nonlocal buffer
+ # 양 끝 공백을 함께 제거한다. `"\n"` 만 벗기면 끝에 남은 `"\n "` 조각이
+ # 빈 줄로 바뀌어 실행마다 빈 줄이 하나씩 늘어난다(멱등 깨짐).
+ # 블록 태그 경계의 공백은 렌더링에 영향이 없으므로 제거해도 안전하다.
text = buffer.strip()
- if text:
- lines.append(pad(depth) + text)
buffer = ""
+ if not text:
+ return
+ for raw_line in text.split("\n"):
+ line = raw_line.strip()
+ if not line:
+ # 문서 맨 앞이나 빈 줄 뒤에는 빈 줄을 더하지 않는다.
+ if lines and lines[-1] != "":
+ lines.append("")
+ continue
+ lines.append(pad(depth) + line)
position = 0
while True:
@@ -259,10 +276,12 @@ def _format_html(source: str, indent: str) -> str:
position = match.end()
raw = match.group(0)
- # 주석·DOCTYPE 등은 한 줄 차지
+ # 주석·DOCTYPE 등은 흐름에 그대로 둔다.
+ # 상세페이지에는 `` 처럼 바로 뒤 요소를
+ # 설명하는 주석이 많다. 줄을 강제로 나누면 라벨과 대상이 떨어져 오히려
+ # 읽기 나빠진다. 원문에서 줄이 나뉘어 있었다면 flush 가 그 줄바꿈을 살린다.
if match.group("comment") or match.group("cdata") or match.group("decl"):
- flush()
- lines.append(pad(depth) + raw.strip())
+ buffer += raw
continue
name = (match.group("name") or "").lower()
diff --git a/app/modules/cafe24/templates/cafe24/_editor.html b/app/modules/cafe24/templates/cafe24/_editor.html
index 69ca46e..a19b20d 100644
--- a/app/modules/cafe24/templates/cafe24/_editor.html
+++ b/app/modules/cafe24/templates/cafe24/_editor.html
@@ -65,12 +65,18 @@
{# 색칠된
위에 투명한