Skip to content

feat(js-core): highlight_phrase / highlight_regex on string displayer#742

Open
paddymul wants to merge 2 commits into
mainfrom
feat/string-highlight-displayer
Open

feat(js-core): highlight_phrase / highlight_regex on string displayer#742
paddymul wants to merge 2 commits into
mainfrom
feat/string-highlight-displayer

Conversation

@paddymul
Copy link
Copy Markdown
Collaborator

Summary

Adds search highlighting to the string displayer. Two new optional fields on StringDisplayerA:

  • highlight_phrase: string | string[] — phrase(s) to highlight (regex-escaped, longest-first alternation so overlapping terms pick the longer match)
  • highlight_regex: string — JS regex source (no slashes/flags)
  • highlight_color: string — any CSS color, defaults to "yellow"

When either is set, the column switches from a valueFormatter to a cell renderer that runs the existing string formatter first (so max_length truncation is preserved) and wraps matches in <mark style={{backgroundColor: color, padding: 0}}>. Matching is case-insensitive. highlight_regex wins if both are supplied; invalid regex sources fall back to plain text with a console.warn. A tooltipValueGetter is added alongside so the full untruncated value is still hoverable.

Usage from Python:

'displayer_args': {
    'displayer': 'string',
    'max_length': 200,
    'highlight_phrase': ['error', 'fail'],   # or a single string, or use highlight_regex
    'highlight_color': '#ffe066',
}

Test plan

  • pnpm test — 214 passed (was 212; +2 new tests covering phrase and regex highlighting)
  • pnpm run build clean (tsc + vite)
  • CI green

Adds optional highlight_phrase (string | string[]) and highlight_regex
fields to StringDisplayerA, plus highlight_color. When set, the column
switches to a cell renderer that wraps matches in <mark> with the given
background. Matching is case-insensitive; regex wins if both are set.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 15, 2026

📦 TestPyPI package published

pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.13.5.dev25942281089

or with uv:

uv pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.13.5.dev25942281089

MCP server for Claude Code

claude mcp add buckaroo-table -- uvx --from "buckaroo[mcp]==0.13.5.dev25942281089" --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo-table

📖 Docs preview

🎨 Storybook preview

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3871b59695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const buildRegexPattern = (source: string): RegExp | undefined => {
if (typeof source !== "string" || source.length === 0) return undefined;
try {
return new RegExp(`(${source})`, "gi");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid wrapping user regexes with capturing groups

When highlight_regex contains a capturing group, raw.split(pattern) includes every captured submatch in the returned array, but the renderer assumes only odd indexes are full matches. For example highlight_regex: "a(b)" on xabz renders x<mark>ab</mark>bz, duplicating the captured b, so valid JS regex sources can corrupt the displayed cell text. Use a non-splitting approach or avoid exposing user captures to split.

Useful? React with 👍 / 👎.

The existing dep was `JSON.stringify(styledColumns)`. After dfToAgrid
processes displayer_args, the relevant change for highlighting is a
function-valued prop flip — cellRenderer goes from undefined to a fn,
valueFormatter goes from fn to undefined. JSON.stringify silently drops
function values, so the stringified signature is identical pre- and
post-flip. useMemo never recomputes, AgGridReact never gets the new
gridOptions, and AG-Grid never sees the new columnDefs.

Replace with `styledColumns` reference. styledColumns is the result of a
useMemo on df_viewer_config; anywidget pushes a fresh tree on every
Python sync so the ref changes meaningfully. The post-dfToAgrid array
is small (one entry per displayed column) so reference comparison is
cheap and precise enough.

Three diagnostic tests in highlight.test.tsx document the blind spot and
sanity-check that a reference dep does see the change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant