c0e8fa6df3a0bd406c4188d49ee00f20aef203e5 max Mon Sep 7 12:07:18 2026 -0700 Substitute trackDb variables in hub track description pages A hub's description page comes straight off the hub's web server and has never been through variable substitution, so a $db or $parentTrack in it reached the reader as literal text. Native trackDb pages are fine, since hgTrackDb substitutes them when it loads trackDb, but there was no equivalent step for a hub. hgc's getTrackHtml and hgTrackUi's trackUi both call hVarSubstTrackDbHtml on a hub track's html. Only a short list of variables is recognized there and nothing is an error, because a hub page written before this existed can easily contain a dollar sign inside a shell example, and silently rewriting that would be worse than not substituting at all. Adds $parentTrack, the name of the container a track sits in, which is what a subtrack description page needs to link back to its superTrack or composite. Views are skipped, since a view has no page of its own, and the hub_<id>_ prefix is kept so the name works as hgTrackUi's g= parameter. Documents $track, $parentTrack and $hgsid in trackDb/README. refs #37599 diff --git src/hg/hgTrackUi/hgTrackUi.c src/hg/hgTrackUi/hgTrackUi.c index 93b76d607be..cccc3d87ba5 100644 --- src/hg/hgTrackUi/hgTrackUi.c +++ src/hg/hgTrackUi/hgTrackUi.c @@ -2,30 +2,31 @@ * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "cheapcgi.h" #include "htmshell.h" #include "jksql.h" #include "jsHelper.h" #include "trackDb.h" #include "hgTrackUi.h" #include "quickLift.h" #include "hdb.h" #include "hCommon.h" #include "hui.h" +#include "hVarSubst.h" #include "fileUi.h" #include "ldUi.h" #include "snpUi.h" #include "snp125Ui.h" #include "snp125.h" #include "sample.h" #include "wiggle.h" #include "hgMaf.h" #include "obscure.h" #include "chainCart.h" #include "chainDb.h" #include "gvUi.h" #include "grp.h" #include "oregannoUi.h" #include "chromGraph.h" @@ -4669,30 +4670,33 @@ if (tdb == NULL) { errAbort("Can't find %s in track database %s chromosome %s", track, database, chromosome); } // Do little more dupe handling - make a tdb for dupe if any if (isDup) { struct dupTrack *dup = dupTrackFindInList(dupList, dupWholeName); if (dup == NULL) errAbort("Can't find duplicate track %s", dupWholeName); tdb = dupTdbFrom(tdb, dup); } +// A hub's description page never went through hgTrackDb, so its variables are substituted +// here instead. This is what lets a hub page link to its container with $parentTrack. +hVarSubstTrackDbHtml(cart, tdb, database); if(cartOptionalString(cart, "ajax")) { // html is going to be used w/n a dialog in hgTracks.js so serve up stripped down html // still need CSP2 header for security printf("%s", getCspMetaHeader()); trackUi(tdb, tdbList, ct, TRUE); cartRemove(cart,"ajax"); jsInlineFinish(); } else { // htmlNoEscape() below lets the <span> through, so the labels themselves have to be // escaped here - they come from trackDb, which a track hub controls struct dyString *title = dyStringNew(0);