Skip to content

Allow tip format functions to return DOM nodes for rich text#2444

Open
kirthi-b wants to merge 1 commit into
observablehq:mainfrom
kirthi-b:feat/tip-title-markup
Open

Allow tip format functions to return DOM nodes for rich text#2444
kirthi-b wants to merge 1 commit into
observablehq:mainfrom
kirthi-b:feat/tip-title-markup

Conversation

@kirthi-b

Copy link
Copy Markdown

Closes the long-standing request for rich text and markup in tips (#1767).

This implements the "relatively easy" direction that mbostock outlined in the thread: a custom format function for the title channel, or any other channel, may now return a DOM node instead of a string. The returned node is appended directly to the tip rather than being wrapped in a text node, so you can style and hyperlink tip content, for example with an SVG tspan or anchor element built with Hypertext Literal:

Plot.tip(data, {
  title: "name",
  format: {
    title: (name) => htl.svg`<tspan><tspan font-weight="bold">${name}</tspan> <a fill="blue" href="/details/${name}">details</a></tspan>`
  }
})

Safety: only a DOM node returned by a format function is treated as rich content. Plain string formats are unchanged and always rendered as text, so no HTML is ever parsed and this adds no injection surface. Because a returned node is appended as-is rather than measured, the lineWidth and textOverflow options do not apply to it.

Changes:

  • src/marks/tip.js: append a returned node directly in renderLine, and route a title-channel node through renderLine; small isNode helper.
  • src/marks/tip.d.ts: TipFormat may now return string | Node.
  • docs/marks/tip.md: document the behavior, safety note, and an example.
  • test/plots/tip-format.ts: snapshot tests for a title node and a name-value channel node.

I scoped this to the format-function approach only, and did not add the separate content channel or the href channel also floated in the thread, since those are larger API surfaces you may want to design yourselves. The VersionBadge version in the docs is a placeholder for you to set to whatever you plan to release.

Fixes #1767

A custom format function for the title channel or any other channel may
now return a DOM node, such as an SVG tspan or anchor element, instead of
a string. The returned node is appended directly to the tip rather than
being wrapped in a text node, allowing styled and hyperlinked rich text.
Plain string formats are unchanged and still rendered as text, so this
adds no HTML injection surface.

Fixes observablehq#1767
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow the tip title channel to contain rich text or markup

1 participant