Skip to content

Commit 495b108

Browse files
jk-kim0claudeAtlas
authored
confluence-mdx: emitter가 width 있는 ac:image에 ac:custom-width 속성을 추가합니다 (#947)
## Summary - emitter의 `_figure_attrs_to_ac_image`, `_emit_figure` 두 경로에서 `ac:width` 설정 시 `ac:custom-width="true"` 속성을 함께 추가합니다 - FC(`converter/core.py`)는 `ac:custom-width="true"`가 있어야 `ac:width`를 MDX `width=`로 변환합니다 — 이 속성이 없으면 roundtrip 시 width가 손실됩니다 ## Test plan - [x] `pytest tests/test_mdx_to_storage/test_emitter.py` — 54/54 pass - [x] `pytest tests/ --ignore=tests/test_unused_attachments.py` — 871/871 pass - [x] `make test-reverse-sync` — 42/42 pass --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Atlas <atlas@jk.agent>
1 parent 9402af7 commit 495b108

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

confluence-mdx/bin/mdx_to_storage/emitter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ def _figure_attrs_to_ac_image(img_attrs_str: str) -> str:
257257
filename = os.path.basename(src) if src else ""
258258
ac_attrs = ['ac:align="center"']
259259
if width:
260+
ac_attrs.append('ac:custom-width="true"')
260261
ac_attrs.append(f'ac:width="{width}"')
261262

262263
return (
@@ -339,6 +340,7 @@ def _emit_figure(block: Block, link_resolver: Optional[LinkResolver] = None) ->
339340

340341
attrs = ['ac:align="center"']
341342
if width:
343+
attrs.append('ac:custom-width="true"')
342344
attrs.append(f'ac:width="{width}"')
343345

344346
parts = [f"<ac:image {' '.join(attrs)}>"]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from converter.core import ConfluenceToMarkdown
2+
from mdx_to_storage import emit_document, parse_mdx
3+
4+
5+
def _roundtrip_mdx_via_storage_xhtml(mdx: str, tmp_path) -> str:
6+
xhtml = emit_document(parse_mdx(mdx))
7+
converter = ConfluenceToMarkdown(xhtml)
8+
converter.load_attachments(
9+
input_dir=str(tmp_path),
10+
output_dir="/images",
11+
public_dir=str(tmp_path),
12+
skip_image_copy=True,
13+
)
14+
return converter.as_markdown()
15+
16+
17+
def test_figure_width_survives_storage_roundtrip(tmp_path):
18+
mdx = """<figure>
19+
<img src="/images/path/sample.png" alt="Sample" width="700">
20+
</figure>
21+
"""
22+
23+
markdown = _roundtrip_mdx_via_storage_xhtml(mdx, tmp_path)
24+
25+
assert 'width="700"' in markdown
26+
assert 'src="/images/sample.png"' in markdown
27+
28+
29+
def test_list_item_figure_width_survives_storage_roundtrip(tmp_path):
30+
mdx = """1. Text <br/>
31+
<figure data-layout="center" data-align="center">
32+
<img src="/images/path/sample-image.png" alt="sample-image.png" width="712" />
33+
</figure>
34+
"""
35+
36+
markdown = _roundtrip_mdx_via_storage_xhtml(mdx, tmp_path)
37+
38+
assert 'width="712"' in markdown
39+
assert 'src="/images/sample-image.png"' in markdown

confluence-mdx/tests/test_mdx_to_storage/test_emitter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ def test_emit_figure_to_ac_image_with_width():
242242
xhtml = emit_document(parse_mdx(mdx))
243243
assert (
244244
xhtml
245-
== '<ac:image ac:align="center" ac:width="700"><ri:attachment ri:filename="sample.png"></ri:attachment></ac:image>'
245+
== '<ac:image ac:align="center" ac:custom-width="true" ac:width="700"><ri:attachment ri:filename="sample.png"></ri:attachment></ac:image>'
246246
)
247247

248248

@@ -299,7 +299,7 @@ def test_emit_figure_in_mixed_document():
299299
xhtml = emit_document(parse_mdx(mdx))
300300
assert "<h1>Overview</h1>" in xhtml
301301
assert "<p>Some text.</p>" in xhtml
302-
assert '<ac:image ac:align="center" ac:width="600">' in xhtml
302+
assert '<ac:image ac:align="center" ac:custom-width="true" ac:width="600">' in xhtml
303303
assert '<ri:attachment ri:filename="diagram.png">' in xhtml
304304
assert "<ac:caption><p>Architecture diagram</p></ac:caption>" in xhtml
305305
assert "<p>More text after image.</p>" in xhtml
@@ -552,7 +552,7 @@ def test_emit_list_item_with_figure_becomes_ac_image_sibling():
552552
# <p> should contain only the text (no figure, no trailing br)
553553
assert '<li><p>텍스트</p>' in xhtml
554554
# ac:image should be a sibling of <p>
555-
assert '<ac:image ac:align="center" ac:width="712">' in xhtml
555+
assert '<ac:image ac:align="center" ac:custom-width="true" ac:width="712">' in xhtml
556556
assert '<ri:attachment ri:filename="sample-image.png"></ri:attachment>' in xhtml
557557
# empty <p /> after the image
558558
assert '<p />' in xhtml

0 commit comments

Comments
 (0)