Skip to content

feat: auto-clickable http(s) links in the editor#78

Merged
littlefrontender merged 1 commit into
masterfrom
feat/auto-clickable-links
Jul 8, 2026
Merged

feat: auto-clickable http(s) links in the editor#78
littlefrontender merged 1 commit into
masterfrom
feat/auto-clickable-links

Conversation

@DavertMik

Copy link
Copy Markdown
Contributor

What

Bare http(s):// URLs typed (or pasted) into the editor are now painted as clickable links.

How

A new autoLinkExtension (src/editor/autoLink.ts) adds a ProseMirror inline decoration for every URL — built the same way as the existing @tag badge feature, and for the same reason: it is non-destructive. It only decorates the text, never rewriting the document, so the Markdown round-trips unchanged (a bare URL stays https://example.com, not [https://example.com](https://example.com) — GFM auto-links bare URLs anyway).

  • detectLinks() — pure, unit-tested matcher. Matches http(s)://…, then trims trailing sentence punctuation and unbalanced closing brackets, so see https://example.com. and (https://example.com) link cleanly while a real …/Foo_(bar) URL keeps its parentheses.
  • Skips existing link marks, inline code, and code blocks — URLs are never double-linked or linkified inside code.
  • Opens on Cmd/Ctrl+click (a plain click still places the cursor for editing — the VS Code / GitHub convention). Pass autoLinkExtension({ openOnPlainClick: true }) to open on a plain click instead. Links open in a new tab with noopener,noreferrer.

Wired into the demo editor (App.tsx) and exported from the package (autoLinkExtension, AutoLinkExtension, detectLinks, LinkMatch). Styling added in styles.css (light + dark), reusing the existing primary-blue tokens.

Test plan

  • npx vitest run — 210 passed (17 new detectLinks cases covering schemes, prose embedding, punctuation trimming, balanced vs. unbalanced parens, and negative cases)
  • tsc -b clean
  • npm run build clean

🤖 Generated with Claude Code

Paint bare `http(s)://` URLs as clickable links via a ProseMirror inline
decoration, mirroring the tag-badge extension. The decoration is
non-destructive: it never rewrites the document, so a bare URL stays a bare
URL in the Markdown output (GFM auto-links these anyway) instead of becoming
`[url](url)`.

- `detectLinks()` matches `http(s)://…` then trims trailing sentence
  punctuation and unbalanced closing brackets, so prose like
  `see https://example.com.` and `(https://example.com)` link cleanly while
  balanced parens in the URL itself are preserved.
- Existing link marks, inline `code`, and code blocks are skipped so URLs are
  never double-linked or linkified inside code.
- Links open in a new tab on Cmd/Ctrl+click (a plain click still edits the
  text); pass `{ openOnPlainClick: true }` to open on a plain click instead.

Wired into the demo editor and exported from the package. Adds unit tests for
the pure `detectLinks()` matcher.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying blocks with  Cloudflare Pages  Cloudflare Pages

Latest commit: 38a149c
Status: ✅  Deploy successful!
Preview URL: https://e5f22832.blocks-cno.pages.dev
Branch Preview URL: https://feat-auto-clickable-links.blocks-cno.pages.dev

View logs

Comment thread src/editor/autoLink.ts
@offtop offtop self-requested a review July 3, 2026 09:09
Comment thread src/editor/autoLink.ts
href: string;
}

function countChar(text: string, char: string): number {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this will work with non char values but with strings as well

function countChar(text: string, stringToCount: string) {
  return text.split(stringToCount).length - 1;
}
> 'test'.split("t").length - 1;
2
> 'test'.split("te").length - 1;
1
> 'testtest'.split("te").length - 1;
2

@littlefrontender littlefrontender merged commit c476795 into master Jul 8, 2026
3 checks passed
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.

3 participants