From 2cc22b1b0fe774615d6408d111ba42d145dee96d Mon Sep 17 00:00:00 2001 From: JK Date: Thu, 19 Feb 2026 23:23:07 +0900 Subject: [PATCH] =?UTF-8?q?confluence-mdx:=20xhtml=5Fpatcher=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=20=EB=92=A4=20=EC=A1=B0=EC=82=AC=20?= =?UTF-8?q?=EC=95=9E=20=EA=B3=B5=EB=B0=B1=20=EC=A0=9C=EA=B1=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=98=AC=EB=B0=94=EB=A5=B4=EA=B2=8C=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IDENTIFIER 뒤 텍스트 노드의 leading whitespace가 diff에서 삭제된 경우, xhtml_patcher가 해당 공백을 제거하지 못하는 버그를 수정합니다. 직전 텍스트 노드 범위와 현재 텍스트 노드 범위 사이의 gap이 diff로 삭제된 경우(gap_new == ''), leading whitespace를 제거하도록 수정합니다. Co-Authored-By: Claude Sonnet 4.6 --- .../bin/reverse_sync/xhtml_patcher.py | 15 +++++++++++- .../tests/test_reverse_sync_xhtml_patcher.py | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/confluence-mdx/bin/reverse_sync/xhtml_patcher.py b/confluence-mdx/bin/reverse_sync/xhtml_patcher.py index 8d7fdac6a..bedb1e00d 100644 --- a/confluence-mdx/bin/reverse_sync/xhtml_patcher.py +++ b/confluence-mdx/bin/reverse_sync/xhtml_patcher.py @@ -290,9 +290,22 @@ def _apply_text_changes(element: Tag, old_text: str, new_text: str): ) node_str = str(node) - # 원본 whitespace 보존 + # 원본 whitespace 보존 (단, diff에서 삭제된 선행 공백은 제거) leading = node_str[:len(node_str) - len(node_str.lstrip())] trailing = node_str[len(node_str.rstrip()):] + + # 직전 노드 범위와 현재 노드 범위 사이의 gap이 diff로 삭제된 경우, + # leading whitespace를 제거한다. + # 예: IDENTIFIER 조사 → IDENTIFIER조사 (공백 교정) + if leading and i > 0: + prev_end = node_ranges[i - 1][1] + if prev_end < node_start: + gap_new = _map_text_range( + old_stripped, new_stripped, opcodes, prev_end, node_start + ) + if not gap_new: + leading = '' + node.replace_with(NavigableString(leading + new_node_text + trailing)) diff --git a/confluence-mdx/tests/test_reverse_sync_xhtml_patcher.py b/confluence-mdx/tests/test_reverse_sync_xhtml_patcher.py index 0b3614157..5621badf0 100644 --- a/confluence-mdx/tests/test_reverse_sync_xhtml_patcher.py +++ b/confluence-mdx/tests/test_reverse_sync_xhtml_patcher.py @@ -237,3 +237,27 @@ def test_legacy_patch_without_action_treated_as_modify(self): 'new_plain_text': 'New text'}] result = patch_xhtml(xhtml, patches) assert 'New text' in result + + +def test_remove_space_before_korean_particle_after_strong(): + """ 뒤 조사 앞 공백 제거를 올바르게 패치한다. + + XHTML:

... AGENT_SECRET 를 변경해도 괜찮은가요?

+ 교정: 'AGENT_SECRET 를' → 'AGENT_SECRET를' (공백 제거) + + old_plain_text는 xhtml_plain_text(element.get_text())에서 오므로 double-space를 포함. + 다음 text node의 leading whitespace가 diff에서 삭제된 경우, + xhtml_patcher가 해당 공백도 제거해야 한다. + """ + xhtml = '

Q: 운영 도중 AGENT_SECRET 를 변경해도 괜찮은가요?

' + patches = [ + { + 'xhtml_xpath': 'h3[1]', + # old_plain_text는 element.get_text()에서 오므로 XHTML 그대로의 공백 포함 + 'old_plain_text': 'Q: 운영 도중 AGENT_SECRET 를 변경해도 괜찮은가요?', + 'new_plain_text': 'Q: 운영 도중 AGENT_SECRET를 변경해도 괜찮은가요?', + } + ] + result = patch_xhtml(xhtml, patches) + assert 'AGENT_SECRET를 변경해도' in result + assert 'AGENT_SECRET 를 변경해도' not in result