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__ 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/hgc/hgc.c src/hg/hgc/hgc.c index 8e77cb226f4..99bb876867d 100644 --- src/hg/hgc/hgc.c +++ src/hg/hgc/hgc.c @@ -18,30 +18,31 @@ #include "errAbort.h" #include "dystring.h" #include "nib.h" #include "cheapcgi.h" #include "htmshell.h" #include "cart.h" #include "jksql.h" #include "dnautil.h" #include "dnaseq.h" #include "fa.h" #include "fuzzyFind.h" #include "seqOut.h" #include "hdb.h" #include "spDb.h" #include "hui.h" +#include "hVarSubst.h" #include "hgRelate.h" #include "htmlPage.h" #include "psl.h" #include "cogs.h" #include "cogsxra.h" #include "bed.h" #include "cgh.h" #include "agpFrag.h" #include "agpGap.h" #include "ctgPos.h" #include "contigAcc.h" #include "ctgPos2.h" #include "clonePos.h" #include "bactigPos.h" #include "rmskOut.h" @@ -3764,32 +3765,37 @@ * freeze, as indicated by the "origAssembly" trackDb setting */ { trackDbPrintOrigAssembly(tdb, database); } static char *getHtmlFromSelfOrParent(struct trackDb *tdb, char *liftDb) /* Get html from self or from parent if not in self. */ { for (;tdb != NULL; tdb = tdb->parent) { if (sameString(trackHubSkipHubName(tdb->track), "quickLiftChain")) tdb->html = hFileContentsOrWarning(hHelpFile(trackHubSkipHubName(tdb->track))); if (liftDb && isEmpty(tdb->html)) tdb->html = getTrackHtml(liftDb, tdb->table); if (tdb->html != NULL && tdb->html[0] != 0) + { + // a hub's description page never went through hgTrackDb, substitute its variables + // here. tdb is the track the html belongs to, so $parentTrack means its container. + hVarSubstTrackDbHtml(cart, tdb, database); return tdb->html; } + } return NULL; } void printTrackHtml(struct trackDb *tdb) /* If there's some html associated with track print it out. Also print * last update time for data table and make a link * to the TB table schema page for this table. */ { // safety net: a few detail pages never print a position, so flush the iframe here printPendingIframe(); if (!isCustomTrack(tdb->track) && !isMyVariantsType(tdb->type)) { printRelatedTracks(database, trackHash, tdb, cart); extraUiLinks(database, tdb, cart); printTrackUiLink(tdb);