@@ -311,23 +311,67 @@ def format_types_section(types_text):
311311
312312# ─── Formatting Helpers ──────────────────────────────────────────────────────
313313
314+ # Cache of template_id -> the template's own display name (its top-level
315+ # "Name", e.g. "JRC2018U"). An Images/Examples entry's own "id"/"label"
316+ # describe the depicted individual or class instance, not the template it is
317+ # aligned to — so "aligned to <template>" text needs this separate lookup.
318+ # The handful of templates VFB uses are shared across every page, so a
319+ # process-wide cache keeps this to one extra request per template, not per page.
320+ _template_label_lock = threading .Lock ()
321+ _template_label_cache = {}
322+
323+ def get_template_label (template_id ):
324+ """Resolve a template's own display name for 'aligned to <template>' text.
325+
326+ Falls back to the raw template_id if the lookup fails.
327+ """
328+ with _template_label_lock :
329+ cached = _template_label_cache .get (template_id )
330+ if cached is not None :
331+ return cached
332+ label = template_id
333+ template_data = fetch_term_info (template_id )
334+ if template_data :
335+ label = template_data .get ("Name" , template_id )
336+ with _template_label_lock :
337+ _template_label_cache [template_id ] = label
338+ return label
339+
314340def get_thumbnails (term_data ):
315341 """Extract thumbnail URLs from Images (individuals) or Examples (classes).
316342
317- Returns list of dicts: {url, label, template_id}
343+ Returns list of dicts: {url, alt, template_id, image_id}.
344+
345+ `alt` is a fully descriptive caption: "<tags> <name> (<id>) aligned to
346+ <template>". `image_id` is the specific depicted term — the page's own Id
347+ for an individual, a distinct instance Id for a class's Examples — and
348+ together with `template_id` builds the 3D-browser deep link in
349+ build_hero_card (?id=<page id>&i=<template_id>,<image_id>), so the
350+ thumbnail actually opens showing that image on that template.
318351 """
319352 thumbnails = []
353+ term_id = term_data .get ("Id" , "" )
354+ term_name = term_data .get ("Name" , "" )
355+ tags_text = " " .join (t .replace ("_" , " " ) for t in term_data .get ("Tags" , []))
356+
357+ def make_alt (label , image_id , template_id ):
358+ template_label = get_template_label (template_id )
359+ caption = f'{ label } ({ image_id } ) aligned to { template_label } '
360+ return f'{ tags_text } { caption } ' if tags_text else caption
320361
321362 # Individual terms have Images
322363 images = term_data .get ("Images" , {})
323364 if images :
324365 for template_id , image_list in images .items ():
325366 for img in image_list :
326367 if img .get ("thumbnail" ):
368+ image_id = img .get ("id" , term_id )
369+ label = img .get ("label" , term_name )
327370 thumbnails .append ({
328371 "url" : img ["thumbnail" ],
329- "label " : img . get ( " label" , term_data . get ( "Name" , "" ) ),
372+ "alt " : make_alt ( label , image_id , template_id ),
330373 "template_id" : template_id ,
374+ "image_id" : image_id ,
331375 })
332376
333377 # Class terms have Examples
@@ -336,10 +380,13 @@ def get_thumbnails(term_data):
336380 for template_id , example_list in examples .items ():
337381 for ex in example_list :
338382 if ex .get ("thumbnail" ):
383+ image_id = ex .get ("id" , term_id )
384+ label = ex .get ("label" , term_name )
339385 thumbnails .append ({
340386 "url" : ex ["thumbnail" ],
341- "label " : ex . get ( " label" , term_data . get ( "Name" , "" ) ),
387+ "alt " : make_alt ( label , image_id , template_id ),
342388 "template_id" : template_id ,
389+ "image_id" : image_id ,
343390 })
344391
345392 return thumbnails [:4 ] # Limit to 4
@@ -441,13 +488,13 @@ def format_downloads(images):
441488
442489 lines = []
443490 for template_id , image_list in images .items ():
491+ template_label = get_template_label (template_id )
444492 for img in image_list :
445- template_label = template_id
446493 has_downloads = any (img .get (k ) for k in ("nrrd" , "obj" , "swc" , "wlz" ))
447494 if not has_downloads :
448495 continue
449496
450- lines .append (f'Image files aligned to { img . get ( "label" , template_label ) } :' )
497+ lines .append (f'Image files aligned to { template_label } :' )
451498 lines .append ("" )
452499 if img .get ("obj" ):
453500 lines .append (f'- [Pointcloud (OBJ)]({ img ["obj" ]} )' )
@@ -558,9 +605,10 @@ def build_hero_card(name, term_id, tags_badges, description_html, comment_html,
558605 ]
559606
560607 for thumb in thumbnails :
608+ viewer_url = f'{ VFB_BROWSER_BASE } ?id={ term_id } &i={ thumb ["template_id" ]} ,{ thumb ["image_id" ]} '
561609 lines .append (
562- f' <a href="{ VFB_BROWSER_BASE } ?id= { term_id } ">'
563- f'<img src="{ thumb ["url" ]} " alt="{ name } " class="img-fluid rounded" '
610+ f' <a href="{ viewer_url } ">'
611+ f'<img src="{ thumb ["url" ]} " alt="{ thumb [ "alt" ] } " class="img-fluid rounded" '
564612 f'style="max-width:200px; background:#000; margin:4px;"/></a>'
565613 )
566614
0 commit comments