feat(js-core): highlight_phrase / highlight_regex on string displayer#742
feat(js-core): highlight_phrase / highlight_regex on string displayer#742paddymul wants to merge 2 commits into
Conversation
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>
📦 TestPyPI package publishedpip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.13.5.dev25942281089or 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.dev25942281089MCP server for Claude Codeclaude 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 |
There was a problem hiding this comment.
💡 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"); |
There was a problem hiding this comment.
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>
Summary
Adds search highlighting to the
stringdisplayer. Two new optional fields onStringDisplayerA: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
valueFormatterto a cell renderer that runs the existing string formatter first (somax_lengthtruncation is preserved) and wraps matches in<mark style={{backgroundColor: color, padding: 0}}>. Matching is case-insensitive.highlight_regexwins if both are supplied; invalid regex sources fall back to plain text with aconsole.warn. AtooltipValueGetteris added alongside so the full untruncated value is still hoverable.Usage from Python:
Test plan
pnpm test— 214 passed (was 212; +2 new tests covering phrase and regex highlighting)pnpm run buildclean (tsc + vite)