"""Self-contained review HTML. OCR text is escaped, never executed.""" import base64,html,json from pathlib import Path from display_language import english_message def render(job,cfg): esc=lambda s:html.escape(str(s),quote=True) from context_export import page_context, adoption_notice sections=[] for idx in cfg['selected']: folder=Path(job)/f'page-{idx+1:05d}' if not (folder/'source.png').exists():continue image=base64.b64encode((folder/'source.png').read_bytes()).decode() error=json.loads((folder/'review-error.json').read_text()).get('error','') if (folder/'review-error.json').exists() else '' status='Suggestions available; approve or reject in the app' if (folder/'review.json').exists() else 'Not reviewed by Gemma' blocks=[] if (folder/'regions.json').exists(): regions=json.loads((folder/'regions.json').read_text())['regions'] for r in regions: blocks.append(f'
{esc(r["role"])} · Region {r["id"]+1} · Coordinates {esc(r["box"])}
{esc(r["text"])}
') else: text=(folder/'original.md').read_text() if (folder/'original.md').exists() else 'OCR incomplete' blocks=[f'

No region data; using the saved OCR reading order.

{esc(text)}
'] context=page_context(folder) blocks.insert(0,'

Text for model input

'+esc(context['status'])+'

'+esc(context['text'])+'

Applied changes

'+esc(json.dumps(context['edits'],ensure_ascii=False,indent=2))+'

Suggestions requiring review; not applied to the text

'+esc(json.dumps(context['pending'],ensure_ascii=False,indent=2))+'

Unverified model notes: '+esc(' / '.join(context['notes']))+'

') sections.append(f'

Page {idx+1}

{esc(english_message(error or status))}

Source page {idx+1}
{"".join(blocks)}
') return 'OCR review document

Model input text, suggestions and source images

Region order is detected automatically. Check it against the images. Original OCR is preserved. Model input text is original OCR or explicitly adopted content, including optional Quick mode candidates without manual verification. Unapproved suggestions are listed separately for review.

'+esc(adoption_notice(job,cfg))+'

'+''.join(sections)+''