FIX 1: _content_has_local_images and extract_local_images now skip lines inside ``` fences so a local-image ref inside a code block is not treated as real. FIX 2: md_translate.translate() tracks fence state; callout/columns/mention transforms are suppressed for lines inside ``` ... ``` blocks (pass verbatim). FIX 3: main() catches NtnUploadError and prints a clean error + e.stderr before sys.exit(1); body moved to _main_body(parser, args). FIX 4: ntn_files.upload() raises NtnUploadError on empty stdout instead of IndexError, giving a clean message combined with FIX 3. FIX 5: Removed unused write_to_page() (both page paths are inlined). FIX 6: create_page_markdown() omits the 'markdown' key when value is falsy, avoiding empty-markdown sends on DB rows created without --file/--stdin. FIX 7: CLAUDE.md documents --allow-deleting-content scope (markdown engine only). TDD: Added test_fence_passthrough_no_transform (md_translate, suite now 8) and test_local_image_inside_fence_ignored (engine_routing, suite now 6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
102 lines
2.8 KiB
Python
102 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
||
"""Tests for md_translate.py — run with `python test_md_translate.py`."""
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
sys.path.insert(0, str(Path(__file__).parent))
|
||
|
||
import md_translate
|
||
|
||
|
||
def test_passthrough_basics():
|
||
src = "# Heading\n\n- item\n\n```python\nx=1\n```"
|
||
assert md_translate.translate(src) == src
|
||
|
||
|
||
def test_callout_note():
|
||
out = md_translate.translate("> [!NOTE]\n> Be careful")
|
||
assert '<callout icon="ℹ️" color="blue_bg">' in out
|
||
assert "\tBe careful" in out
|
||
assert "</callout>" in out
|
||
|
||
|
||
def test_callout_warning_color():
|
||
out = md_translate.translate("> [!WARNING]\n> Danger")
|
||
assert 'color="yellow_bg"' in out
|
||
assert 'icon="⚠️"' in out
|
||
|
||
|
||
def test_columns():
|
||
src = "::: columns\n::: column\nLeft\n:::\n::: column\nRight\n:::\n:::"
|
||
out = md_translate.translate(src)
|
||
assert "<columns>" in out
|
||
assert out.count("<column>") == 2
|
||
assert "</columns>" in out
|
||
assert "\tLeft" in out or "\t\tLeft" in out
|
||
|
||
|
||
def test_toggle_children_indented():
|
||
src = "<details>\n<summary>More</summary>\nBody line\n</details>"
|
||
out = md_translate.translate(src)
|
||
assert "<summary>More</summary>" in out
|
||
assert "\tBody line" in out
|
||
|
||
|
||
def test_mention_url():
|
||
out = md_translate.translate(
|
||
"See @[ADR](https://notion.so/X-abcdef0123456789abcdef0123456789).")
|
||
assert "<mention-page url=" in out
|
||
assert ">ADR</mention-page>" in out
|
||
|
||
|
||
def test_mention_invalid_plain():
|
||
out = md_translate.translate("ping @[Bob](not-an-id)")
|
||
assert "@Bob" in out
|
||
assert "mention-page" not in out
|
||
|
||
|
||
def test_fence_passthrough_no_transform():
|
||
"""Lines inside fenced code blocks must pass through verbatim — no callout,
|
||
columns, or mention transformation applied."""
|
||
raw_id = "abcdef0123456789abcdef0123456789"
|
||
src = (
|
||
"```\n"
|
||
"> [!NOTE]\n"
|
||
"::: columns\n"
|
||
f"@[Page]({raw_id})\n"
|
||
"```"
|
||
)
|
||
out = md_translate.translate(src)
|
||
# No transformation should have occurred
|
||
assert "<callout" not in out, "callout must not be emitted inside fence"
|
||
assert "<columns>" not in out, "columns must not be emitted inside fence"
|
||
assert "<mention-page" not in out, "mention must not be emitted inside fence"
|
||
# Original lines must be present verbatim
|
||
assert "> [!NOTE]" in out
|
||
assert "::: columns" in out
|
||
assert f"@[Page]({raw_id})" in out
|
||
|
||
|
||
def run_all():
|
||
tests = [
|
||
test_passthrough_basics,
|
||
test_callout_note,
|
||
test_callout_warning_color,
|
||
test_columns,
|
||
test_toggle_children_indented,
|
||
test_mention_url,
|
||
test_mention_invalid_plain,
|
||
test_fence_passthrough_no_transform,
|
||
]
|
||
for t in tests:
|
||
print(f"\n{t.__name__}")
|
||
t()
|
||
print("\n" + "=" * 50)
|
||
print(f"✅ All {len(tests)} tests passed")
|
||
print("=" * 50)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
run_all()
|