back to table · edit · history · where entries came from · files · download
4467 bytes, as of the version from 2026-11-11 07:57 (current). Recorded here, not run.
"""Render a saved authenticated live HTML page without exposing API credentials.
Run: python render_check.py before|after
Requires Playwright and Chromium; TMPDIR contains snapshots from fetch_live.py.
"""
import os,sys,json,re,hashlib,platform,importlib.metadata
from pathlib import Path
from playwright.sync_api import sync_playwright
W=Path(os.environ.get('TMPDIR', Path(__file__).resolve().parent)); phase=sys.argv[1]
assert phase in ('before','after')
doc=json.loads((W/(phase+'-document.json')).read_text())
rels=doc['Similar tables']
rels=list(rels.values()) if isinstance(rels,dict) else rels
with sync_playwright() as p:
browser=p.chromium.launch(headless=True,args=['--no-sandbox','--disable-dev-shm-usage','--disable-gpu'])
page=browser.new_page(viewport={'width':1440,'height':1100})
errors=[]
page.on('pageerror',lambda e:errors.append(str(e)))
page.route('https://numberdb.org/T713',lambda r:r.fulfill(status=200,content_type='text/html',body=(W/(phase+'-page.html')).read_text()))
page.goto('https://numberdb.org/T713',wait_until='domcontentloaded')
page.wait_for_function('typeof MathJax !== "undefined" && !!MathJax.typesetPromise',timeout=30000)
page.evaluate('MathJax.typesetPromise()')
page.locator('details.prose-more').evaluate_all('(els)=>els.forEach(e=>e.open=true)')
text=page.locator('body').inner_text()
(W/(phase+'-rendered-text.txt')).write_text(text)
heading=page.get_by_text('Similar tables',exact=True)
out={'phase':phase,'heading_count':heading.count(),'page_errors':errors,'math_errors':page.locator('mjx-merror').count(),
'decimal_count':sum(s in text for ks in doc['Numbers'].values() for xs in ks.values() for s in xs.values()),
'relationships':[],'python':platform.python_version(),'playwright':importlib.metadata.version('playwright'),'chromium':browser.version,
'html_sha256':hashlib.sha256((W/(phase+'-page.html')).read_bytes()).hexdigest(),
'method':'Authenticated live HTML replayed at its original URL; public assets fetched without API credentials.'}
if heading.count():
section=heading.locator('xpath=following-sibling::div[1]')
section_text=section.inner_text()
out['section_text']=section_text
out['section_links']=section.locator('a').evaluate_all('(els)=>els.map(e=>({text:e.innerText,href:e.href}))')
section.screenshot(path=str(W/(phase+'-similar-tables.png')))
for rel in rels:
target,label=re.search(r'HREF\{(T\d+)\}\[([^]]+)\]',rel).groups()
# HREF and CITE renderer expands labels; check complete sentence text around citations separately.
target_links=section.locator('a.HREF').filter(has_text=label)
href=target_links.evaluate('(e)=>e.href')
assert href=='https://numberdb.org/'+target
response=page.request.get(href)
expected=re.sub(r'HREF\{[^}]+\}\[([^]]+)\]',r'\1',rel)
for cite in re.findall(r'CITE\{([^}]+)\}',expected):
caption=section.locator('a[href="#'+cite+'"]').inner_text()
expected=expected.replace('CITE{'+cite+'}',caption)
actual=target_links.locator('..').inner_text()
out['relationships'].append({'target':target,'label':label,'label_visible':label in section_text,'links':target_links.count(),
'href':href,'target_http_status':response.status,
'full_sentence_preserved':actual==expected,'rendered_sentence':actual})
page.screenshot(path=str(W/(phase+'-rendered-full.png')),full_page=True)
links=page.locator('a').evaluate_all('(els)=>els.map(e=>({text:e.innerText,href:e.href}))')
out['missing_fragment_targets']=[a['href'] for a in links if a['href'].startswith('https://numberdb.org/T713#') and page.locator('[id="'+a['href'].split('#',1)[1]+'"]').count()==0]
(W/(phase+'-browser-results.json')).write_text(json.dumps(out,indent=2)+'\n')
print(json.dumps(out,indent=2))
browser.close()
if phase=='after':
assert out['heading_count']==1 and out['decimal_count']==98
assert not out['math_errors'] and not out['page_errors'] and not out['missing_fragment_targets']
assert len(out['relationships'])==4 and all(r['label_visible'] and r['links']==1 and r['target_http_status']==200 and r['full_sentence_preserved'] for r in out['relationships'])
else:
assert out['heading_count']==0