@@ -90,6 +90,16 @@ function templateDescription(t: MetaData): string | undefined {
9090 return typeof v === "string" && v . length > 0 ? v : undefined ;
9191}
9292
93+ /** Page-placement node for a metadata object resolved by short name, with the
94+ * SAME package-less fallback the Payload cross-link and field hrefs share: when
95+ * the object can't be resolved off the root, fall back to a root-level node so a
96+ * link is still emitted. Keeps every inbound href routing through the one
97+ * `docPageHref(layout, …)` placement. */
98+ function pageNodeByName ( root : MetaRoot | undefined , name : string ) : DocPageNode {
99+ const obj = root ?. findObject ( name ) ;
100+ return obj !== undefined ? docPageNode ( obj ) : { name } ;
101+ }
102+
93103/** Build the TemplateDocData for one `template.output` node. */
94104export function buildTemplateDocData (
95105 template : MetaData ,
@@ -140,13 +150,12 @@ export function buildTemplateDocData(
140150
141151 // Cross-link to the payload entity's page. The href is derived from the SAME
142152 // page-placement function used to write that entity page, so it resolves in
143- // BOTH layouts. Resolve the payload's package from the root (by short name)
144- // so package layout can fold the correct relative path; fall back to a
145- // package-less node (root-level) when it can't be resolved.
146- const payloadObj = root ?. findObject ( payloadName ) ;
147- const payloadTarget : DocPageNode =
148- payloadObj !== undefined ? docPageNode ( payloadObj ) : { name : payloadName } ;
149- const payloadLink = docPageHref ( layout , docPageNode ( template ) , payloadTarget ) ;
153+ // BOTH layouts (package layout folds the correct relative path).
154+ const payloadLink = docPageHref (
155+ layout ,
156+ docPageNode ( template ) ,
157+ pageNodeByName ( root , payloadName ) ,
158+ ) ;
150159
151160 const data : TemplateDocData = {
152161 generatedMarker : `<!-- ${ GENERATED_HEADER } — DO NOT EDIT. -->` ,
@@ -232,15 +241,9 @@ function buildTemplateSourceSection(args: BuildSectionArgs): string | undefined
232241
233242 // Layout-aware field href: route through the SAME docPageHref the Payload
234243 // cross-link uses, so the link lands on the owner VO's REAL page in BOTH
235- // layouts (flat → `./Owner.md`, package → `../<pkg>/Owner.md`). Resolve the
236- // owner's package off the root (by short name); fall back to a package-less
237- // node when it can't be resolved — mirroring the Payload link's fallback.
238- const fieldHref = ( owner : string , name : string ) : string => {
239- const ownerObj = root . findObject ( owner ) ;
240- const toNode : DocPageNode =
241- ownerObj !== undefined ? docPageNode ( ownerObj ) : { name : owner } ;
242- return `${ docPageHref ( layout , fromNode , toNode ) } #${ fieldAnchorSlug ( name ) } ` ;
243- } ;
244+ // layouts (flat → `./Owner.md`, package → `../<pkg>/Owner.md`).
245+ const fieldHref = ( owner : string , name : string ) : string =>
246+ `${ docPageHref ( layout , fromNode , pageNodeByName ( root , owner ) ) } #${ fieldAnchorSlug ( name ) } ` ;
244247
245248 const resolvePartialHref = makePartialHrefResolver ( root , layout , fromNode ) ;
246249 const isMultipart = refs . length > 1 || refs . some ( ( r ) => r . label !== undefined ) ;
0 commit comments