Skip to content

Library link primitive: getLinkProps + LinkProps #752

Description

@romain-pm

Part of #749, API sketch in its first comment. The props tier: everything mechanical about turning a target into anchor data.

  • getLinkProps(target, options, context){ anchor, state }. anchor is DOM-spreadable by construction (href, target, rel, title) — the same contract ImageProps has, so <a {...anchor}> is correct in an Island. state (navigable, isCurrent, isAncestor, label) is separate and is never spread.
  • Not-navigable is a first-class result, not an error: falsy target, "" or whitespace-only string (Jahia/jahia.com NavBar.tsx:66 emits href: "" today), a string failing the scheme allow-list, a falsy return from buildNodeUrl, or a missing translation. Never throws — today buildNodeUrl does (urlBuilder.ts:72), and there is no error boundary in the engine or the library.
  • Cache dependency, default on, skipped without a render context. { node } when the target resolves, { uuid } on the raw reference string when it does not — otherwise publishing the target never flushes the cached fallback. Core's nodeLink.jsp:10 registers on the uuid before checking resolution. cacheDependency also accepts an explicit { node } | { path } | { uuid }; { path } is what a JCR-query loop wants (Jahia/jahia.com NavBar.tsx:135).
  • target validated against jmix:link's four values; unknown or unset omits the attribute, never target="". rel="noopener noreferrer" when target resolves to _blank. Both are live/preview guarantees only — EditModeFilter rewrites them in the page builder.
  • isCurrent is identifier equality and is overridable via options; isAncestor is a path-segment test. Not a substring test (luxe NavigationToggler.tsx:32 and industrial both mark /home/news active on /home/newsletter) and not === on node proxies (samples/hydrogen/src/components/NavBar/default.server.tsx:20,27).
  • Scheme allow-list on every string JLink did not build itself, j:url included: http https mailto tel ftp, plus /… and #…. React only substitutes a throwing javascript: URL and matches that scheme alone; data:, blob: and vbscript: are covered by nothing else.
  • parameters and hash compose correctly: query before fragment. appendParameters (urlBuilder.ts:8-14) splits on ? today, so it would produce #main?a=b.
  • label is node.getDisplayableName(), with an explicit override.
  • When language is set, check hasI18N(locale) and the target's j:invalidLanguages (Jahia/jahia.com NavBar.tsx:106-120 does both); no translation means not navigable. Decide whether hasI18N also gets exposed to JS.

Component tier, vocabulary reader and cache-key ergonomics are separate issues. The library is engine-provided at runtime, so this ships with an engine release.

Correction: { uuid } does not work today — RenderHelper.renderTag populates the tag before setting the page context, so AddCacheDependencyTag.setUuid throws a swallowed NullPointerException and nothing is registered (#750). { node }, { path } and { flushOnPathMatchingRegexp } work.

First pass in #751.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featA new feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions