Skip to content

fix(tables): stop URL linkification at delimiters, not whitespace - #10570

Open
Abdulrehman-PIAIC80387 wants to merge 3 commits into
marimo-team:mainfrom
Abdulrehman-PIAIC80387:fix/table-url-linkification-greedy-10567
Open

fix(tables): stop URL linkification at delimiters, not whitespace#10570
Abdulrehman-PIAIC80387 wants to merge 3 commits into
marimo-team:mainfrom
Abdulrehman-PIAIC80387:fix/table-url-linkification-greedy-10567

Conversation

@Abdulrehman-PIAIC80387

@Abdulrehman-PIAIC80387 Abdulrehman-PIAIC80387 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

📝 Summary

Closes #10567

The table-cell URL linkifier matched URLs with https?://\S+, so a URL embedded in JSON text had the trailing "}] delimiters swallowed into the href.

import polars as pl
pl.DataFrame({"attachments": ['[{"name":"inv.pdf","url":"https://example.com/p/AAA"}]']})

The rendered link pointed at https://example.com/p/AAA%22%7D] (the "}] percent-encoded into the href) instead of https://example.com/p/AAA.

🔍 Root cause

frontend/src/utils/url-parser.ts (the table linkifier used by data-table/columns.tsx):

const urlRegex = /(https?:\/\/\S+)/;

\S+ matches any non-whitespace, so with no whitespace before the closing "}] it keeps consuming those delimiters.

🔧 What changed

Match a URL up to the first character that cannot appear unencoded in a URL (RFC 3986 excluded/"unwise" set — whitespace and " ' < > \ { } | \ ^`) instead of any non-whitespace:

-const urlRegex = /(https?:\/\/\S+)/;
+const urlRegex = /(https?:\/\/[^\s"'<>`{}|\\^]+)/;
  • Applied to the same greedy regex in json/json-parser.ts (the JSON-viewer link conversion), which had the identical bug.
  • Deliberately keeps . , ( ) [ ] etc. valid — real URLs use them (query strings, IPv6 hosts like http://[::1]/, parenthesised paths), so they must not truncate the match.
  • Left urls.ts's ^(https?://\S+)$ alone — it's an anchored whole-string isUrl() check where \S+ is correct.

🎥 Demo

clean-link.mp4

Shows the attachments cell: before, "Copy Link Address" yields https://example.com/p/AAA%22%7D]; after, it yields the clean https://example.com/p/AAA.

🧪 Testing

  • Added regression tests in url-parser.test.ts for the reporter's JSON case and a trailing-quote case.
  • Verified by mutation: reverting the regex to \S+ makes the new tests fail.
  • data-table consumer tests (url-detector, columns) — 87 pass, no regressions.
  • make fe-check (typecheck + lint) clean.
  • Verified manually in make dev (before/after link address as above).

📋 Pre-Review Checklist

  • For large changes, or changes that affect the public API: n/a — small, self-contained bug fix.
  • Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
  • Video or media evidence is provided for any visual changes (optional).

✅ Merge Checklist

  • I have read the contributor guidelines.
  • Documentation has been updated where applicable — n/a.
  • Tests have been added for the changes made.

@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview Aug 18, 2026 6:29am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@mscolnick

Copy link
Copy Markdown
Contributor

@cubic-dev-ai

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai

@mscolnick I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Architecture diagram
sequenceDiagram
    participant UI as Data Table / JSON Viewer
    participant LP as Link Parser (url-parser.ts)
    participant JVP as JSON Value Parser (json-parser.ts)
    participant CT as Column Transformer (columns.tsx)

    Note over UI, CT: Runtime flow when rendering table cells or JSON viewer content

    UI->>CT: render cell(value)
    
    alt Cell is a table column
        CT->>LP: parseContent(textContent)
        LP->>LP: Extract URLs with safe delimiter regex<br/>([^\s"'<>`{}|\\^]+)
        LP-->>CT: Parts array (text + url objects)
        CT-->>UI: Rendered cell with links
    else Cell is JSON viewer content
        CT->>JVP: formatValueForMarkdown(jsonValue)
        JVP->>JVP: Convert plain URLs to markdown links<br/>using same safe delimiter regex
        JVP->>JVP: Apply markdown link replacement
        JVP-->>CT: Markdown string with links
        CT-->>UI: Rendered JSON viewer
    end

    Note over LP, JVP: Shared linkification behavior
    Note over LP: Regex stops at delimiters: " ' < > ` { } | \ ^
    Note over JVP: Same regex applied consistently
    Note over LP, JVP: Preserves valid URL chars: . , ( ) [ ] and query strings
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread frontend/src/utils/json/json-parser.ts Outdated
Comment thread frontend/src/utils/json/json-parser.ts Outdated
The table cell linkifier matched URLs with `https?://\S+`, so a URL
embedded in JSON text (e.g. `..."url":"https://example.com/p/AAA"}]`)
had the trailing `"}]` delimiters swallowed into the href, producing a
broken link like `https://example.com/p/AAA%22%7D]`.

Match a URL up to the first character that cannot appear unencoded in a
URL (the RFC 3986 excluded/"unwise" set: whitespace and `" ' < > ` { } |
\ ^`) instead of any non-whitespace. Characters that are valid in real
URLs (`. , ( ) [ ]` etc.) are intentionally kept, so query strings,
IPv6 hosts, and parenthesised paths are not truncated. Applied to the
same greedy regex in the JSON-viewer link conversion as well.

Closes marimo-team#10567
…ests

Address review:
- Extract the URL character-class regex into a single exported `URL_REGEX`
  in url-parser.ts; json-parser.ts derives its global copy via
  `new RegExp(URL_REGEX.source, "g")`, so the two linkifiers can't drift.
- Add json-parser tests for `jsonToMarkdown`: a URL followed by `"}]`
  stops at the quote, a trailing quote isn't swallowed, and existing
  markdown links are left untouched.
@Abdulrehman-PIAIC80387
Abdulrehman-PIAIC80387 force-pushed the fix/table-url-linkification-greedy-10567 branch from dc4435c to bf21df6 Compare August 18, 2026 06:27
@Light2Dark

Light2Dark commented Aug 18, 2026

Copy link
Copy Markdown
Member

I think would be good to add a benchmark test, regexes like this have a chance to be slow.

@kirangadhave

Copy link
Copy Markdown
Member

Thanks @Abdulrehman-PIAIC80387 for the PR.
I might close this. I have a separate fix for parsing stringified JSON in the cells. That might make this PR moot. I'll verify. If there is still a need after that fix, we can keep this.

@kirangadhave kirangadhave added the bug Something isn't working label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Table: URL linkification is greedy, so URLs inside JSON text get trailing delimiters in the href

4 participants