"""asset_resolver:旧占位符清理与 asset:// 解析。""" import unittest from types import SimpleNamespace from app.features.memoir.asset_resolver import ( collect_asset_ids_for_chapter, collect_asset_ids_from_markdown, resolve_asset_refs_in_markdown, split_markdown_by_asset_refs, strip_legacy_image_placeholders, ) from app.features.memoir.models import Chapter class AssetResolverTest(unittest.TestCase): def test_strip_legacy_image_placeholders_double_brace(self): md = "正文\n\n{{IMAGE:院子里的树}}\n\n结尾" out = strip_legacy_image_placeholders(md) self.assertNotIn("IMAGE", out) self.assertIn("正文", out) self.assertIn("结尾", out) def test_strip_legacy_image_placeholders_quad_brace(self): md = "a\n\n{{{{IMAGE:描述}}}}\n\nb" out = strip_legacy_image_placeholders(md) self.assertNotIn("IMAGE", out) def test_collect_and_split_asset_refs(self): md = "前\n\n![图注](asset://abc-123)\n\n后" self.assertEqual(collect_asset_ids_from_markdown(md), ["abc-123"]) blocks = split_markdown_by_asset_refs(md, lambda aid: f"https://x/{aid}") self.assertEqual(len(blocks), 3) self.assertEqual(blocks[0]["type"], "text") self.assertEqual(blocks[1]["type"], "image") self.assertIn("https://x/abc-123", blocks[1]["url"]) def test_resolve_asset_refs_in_markdown(self): md = "![c](asset://id1)" out = resolve_asset_refs_in_markdown(md, lambda aid: "https://cdn/u") self.assertIn("https://cdn/u", out) self.assertNotIn("asset://", out) def test_collect_asset_ids_for_chapter(self): ch = Chapter( id="c1", user_id="u1", title="t", order_index=0, canonical_markdown="![x](asset://a1)", cover_asset_id="cov1", ) ids = collect_asset_ids_for_chapter(ch) self.assertEqual(ids, {"a1", "cov1"}) def test_collect_asset_ids_includes_linked_story_markdown(self): ch = SimpleNamespace( canonical_markdown="", sections=[], cover_asset_id=None, story_links=[ SimpleNamespace( story=SimpleNamespace( canonical_markdown="![主图](asset://from-story-1)" ) ) ], ) ids = collect_asset_ids_for_chapter(ch) self.assertEqual(ids, {"from-story-1"}) if __name__ == "__main__": unittest.main()