diff --git a/backend/document_mode/diff_report_writer.py b/backend/document_mode/diff_report_writer.py index 9770590..93c730b 100644 --- a/backend/document_mode/diff_report_writer.py +++ b/backend/document_mode/diff_report_writer.py @@ -75,6 +75,46 @@ def _render_diff_list(items: List[str], css_class: str, label: str, icon: str) - """ +def _render_formatting_block(findings: List[Dict]) -> str: + if not findings: + return '' + + def _fmt_value(v): + if isinstance(v, bool): + return 'Bold' if v else 'Regular' + return str(v) + + items = [] + for f in findings: + attr = f.get('attribute', '') + old_v = _fmt_value(f.get('old_value')) + new_v = _fmt_value(f.get('new_value')) + total = f.get('total_span_count', 0) + page_wide = f.get('page_wide', False) + quotes = f.get('example_quotes', []) or [] + + if page_wide: + prefix = f"Page-wide {html.escape(attr)} change: {html.escape(old_v)} β†’ {html.escape(new_v)}" + else: + prefix = f"{html.escape(attr).capitalize()}: {html.escape(old_v)} β†’ {html.escape(new_v)}" + + quote_html = '' + if quotes: + quoted = ', '.join(f'“{html.escape(q)}”' for q in quotes[:3]) + extra = total - len(quotes[:3]) + extra_html = f" …and {extra} more" if extra > 0 else '' + quote_html = f" ({total} span{'s' if total != 1 else ''}): {quoted}{extra_html}" + + items.append(f"
  • {prefix}{quote_html}
  • ") + + return f""" +
    +
    🎨 Formatting changes
    + +
    + """ + + def _render_pair_card(entry: Dict, pair_diffs: Dict) -> str: old = entry['old_page'] new = entry['new_page'] @@ -132,6 +172,7 @@ def _render_pair_card(entry: Dict, pair_diffs: Dict) -> str: blocks.append(_render_diff_list(pair.get('modified') or [], 'block-modified', 'Modified', '✎')) blocks.append(_render_diff_list(pair.get('moved') or [], 'block-moved', 'Moved', '↔')) blocks.append(_render_diff_list(pair.get('style_changes') or [], 'block-style', 'Style changes', '🎨')) + blocks.append(_render_formatting_block(pair.get('formatting_changes') or [])) error_block = '' if pair.get('error'): diff --git a/backend/tests/test_diff_report_formatting_block.py b/backend/tests/test_diff_report_formatting_block.py new file mode 100644 index 0000000..938a83c --- /dev/null +++ b/backend/tests/test_diff_report_formatting_block.py @@ -0,0 +1,65 @@ +"""Smoke test for the new formatting-changes rendering block.""" + +from document_mode.diff_report_writer import _render_formatting_block + + +def test_empty_findings_render_nothing(): + assert _render_formatting_block([]) == '' + + +def test_single_bold_flip_renders_with_quote(): + findings = [{ + 'attribute': 'bold', + 'old_value': True, + 'new_value': False, + 'example_quotes': ['Theft of personal belongings'], + 'total_span_count': 1, + 'page_wide': False, + }] + html_out = _render_formatting_block(findings) + assert '🎨 Formatting changes' in html_out + assert 'Theft of personal belongings' in html_out + assert 'Bold' in html_out + assert 'Regular' in html_out + assert 'block-style' in html_out + + +def test_page_wide_flag_changes_label(): + findings = [{ + 'attribute': 'font', + 'old_value': 'AXASans-Regular', + 'new_value': 'Helvetica', + 'example_quotes': ['Some body text'], + 'total_span_count': 17, + 'page_wide': True, + }] + html_out = _render_formatting_block(findings) + assert 'Page-wide font change' in html_out + + +def test_html_escape_in_quotes(): + findings = [{ + 'attribute': 'bold', + 'old_value': True, + 'new_value': False, + 'example_quotes': [''], + 'total_span_count': 1, + 'page_wide': False, + }] + html_out = _render_formatting_block(findings) + assert '