Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions render/src/pixelrag_render/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,17 @@ def main() -> None:
# Single URL, default CDP backend
pixelshot https://example.com --output ./tiles

# Multiple inputs with 4 workers
pixelshot https://a.com https://b.com --output ./tiles --workers 4
# Multiple inputs
pixelshot https://a.com https://b.com --output ./tiles

# PDF
pixelshot report.pdf --output ./tiles

# Local HTML
pixelshot index.html --output ./tiles --backend playwright

# Pipe URLs from a file
cat urls.txt | xargs pixelshot --output ./tiles --workers 8
# URL file
pixelshot urls.txt --output ./tiles

# Chrome management (folded from the former `pixelrag-chrome`)
pixelshot install-chrome # download the patched headless Chrome
Expand Down Expand Up @@ -294,18 +294,25 @@ def main() -> None:
args = parser.parse_args()
output_dir = Path(args.output)

# Partition inputs into URLs and files for batch processing
urls = []
files = []
for inp in args.inputs:
if inp.startswith("http://") or inp.startswith("https://"):
if inp.lower().endswith(".txt"):
try:
with open(inp, encoding="utf-8") as f:
for line in f:
url = line.strip()
if url:
urls.append(url)
except FileNotFoundError:
parser.error(f"URL file not found: {inp}")
elif inp.startswith("http://") or inp.startswith("https://"):
urls.append(inp)
else:
files.append(Path(inp))

results: list[Path] = []

# Batch-render URLs together for efficiency
if urls:
logger.info(
"Rendering %d URL(s) with backend=%s workers=%d",
Expand Down
53 changes: 53 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import sys
from pathlib import Path

import pytest

# Console scripts live next to the interpreter running the tests (works whether
# invoked via `uv run pytest` or `.venv/bin/python -m pytest`).
_BIN = Path(sys.executable).parent
Expand All @@ -23,6 +25,57 @@ def test_pixelshot_help():
assert "pixelshot" in r.stdout


def test_pixelshot_txt_input_uses_batch_render(monkeypatch, tmp_path, capsys):
from pixelrag_render import render as render_mod

urls_file = tmp_path / "urls.txt"
urls_file.write_text(
"\n https://example.com/a \n\nhttps://example.com/b\nhttps://example.com/c\n"
)
calls = []

def fake_render_urls(urls, output_dir, **kwargs):
calls.append((list(urls), kwargs["workers"]))
return [Path(output_dir) / "a.png.tiles", Path(output_dir) / "c.png.tiles"]

monkeypatch.setattr(render_mod, "render_urls", fake_render_urls)
monkeypatch.setattr(
sys,
"argv",
["pixelshot", str(urls_file), "-o", str(tmp_path / "out"), "-w", "8"],
)

render_mod.main()

assert calls == [
(
[
"https://example.com/a",
"https://example.com/b",
"https://example.com/c",
],
8,
)
]
stdout = capsys.readouterr().out
assert "a.png.tiles" in stdout
assert "b.png.tiles" not in stdout
assert "c.png.tiles" in stdout


def test_pixelshot_missing_txt_input(monkeypatch, tmp_path, capsys):
from pixelrag_render import render as render_mod

missing = tmp_path / "missing.txt"
monkeypatch.setattr(sys, "argv", ["pixelshot", str(missing)])

with pytest.raises(SystemExit) as exc:
render_mod.main()

assert exc.value.code == 2
assert "URL file not found" in capsys.readouterr().err


def test_pixelrag_umbrella_help():
r = _run("pixelrag", "--help")
assert r.returncode == 0
Expand Down