@@ -634,6 +634,52 @@ def test_multiple_shift_enters(self):
634634 assert "A \n B \n C" in out
635635
636636
637+ # ── 리스트 항목의 이미지 자식은 최상위(전체 폭)로 hoist ──────────────────────
638+
639+ class TestListItemImageHoisting :
640+ """Notion에서 이미지가 불릿/번호 항목의 자식으로 들어가면 들여쓰기 없이
641+ 최상위 블록(전체 폭)으로 렌더되어야 한다. 텍스트 자식은 기존대로 들여쓰기 유지."""
642+
643+ def _rt (self , text ):
644+ return [{"plain_text" : text , "annotations" : {"code" : False , "bold" : False , "italic" : False , "strikethrough" : False }, "href" : None }]
645+
646+ def _image_child (self , url = "https://notion/x.png" ):
647+ return {"type" : "image" , "id" : "img-1" , "image" : {"file" : {"url" : url }}, "has_children" : False }
648+
649+ def _list_block (self , b_type , text , children ):
650+ return {"type" : b_type , b_type : {"rich_text" : self ._rt (text )}, "_children" : children , "has_children" : bool (children )}
651+
652+ @patch .object (n , "download_image" , return_value = "/img/blog/x/img-00.png" )
653+ def test_bulleted_image_child_hoisted (self , _dl ):
654+ block = self ._list_block ("bulleted_list_item" , "서버에 나타난다" , [self ._image_child ()])
655+ out = n .block_to_markdown (block , "blog/x" , [0 ])
656+ img_line = next (l for l in out .splitlines () if "![image]" in l )
657+ assert img_line == "" , f"이미지가 들여쓰기됨: { img_line !r} "
658+ assert "- 서버에 나타난다\n \n " in out
659+
660+ @patch .object (n , "download_image" , return_value = "/img/blog/x/img-00.png" )
661+ def test_numbered_image_child_hoisted (self , _dl ):
662+ block = self ._list_block ("numbered_list_item" , "결과" , [self ._image_child ()])
663+ out = n .block_to_markdown (block , "blog/x" , [0 ], 3 )
664+ img_line = next (l for l in out .splitlines () if "![image]" in l )
665+ assert img_line == "" , f"이미지가 들여쓰기됨: { img_line !r} "
666+ assert "3. 결과\n \n " in out
667+
668+ def test_non_image_child_still_indented (self ):
669+ # 회귀: 텍스트 자식(중첩 불릿)은 여전히 2칸 들여쓰기 유지
670+ child = self ._list_block ("bulleted_list_item" , "중첩 항목" , [])
671+ block = self ._list_block ("bulleted_list_item" , "부모" , [child ])
672+ out = n .block_to_markdown (block , "blog/x" , [0 ])
673+ assert " - 중첩 항목" in out
674+
675+ @patch .object (n , "download_image" , return_value = "/img/blog/x/img-00.png" )
676+ def test_image_counter_increments (self , _dl ):
677+ block = self ._list_block ("bulleted_list_item" , "설명" , [self ._image_child ()])
678+ counter = [5 ]
679+ n .block_to_markdown (block , "blog/x" , counter )
680+ assert counter [0 ] == 6
681+
682+
637683# ── TC-14: toggle summary 인라인 마크다운 → HTML 변환 ──────────────────────────
638684
639685class TestToggleSummaryInlineMarkdown :
0 commit comments