Skip to content

fix(desktop): support multi-word #channel name highlighting#229

Merged
wesbillman merged 7 commits intomainfrom
fix-channel-highlight-spaces
Apr 4, 2026
Merged

fix(desktop): support multi-word #channel name highlighting#229
wesbillman merged 7 commits intomainfrom
fix-channel-highlight-spaces

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

@wesbillman wesbillman commented Apr 4, 2026

Summary

  • Fix: #channel name highlighting now supports multi-word names with spaces (previously only the first word was highlighted)
  • Refactor: Extracted shared createRemarkPrefixPlugin factory and detectPrefixQuery helper to eliminate duplication between @mention and #channel highlighting systems
  • Perf: Memoized remarkPlugins array to avoid unnecessary remark re-parsing on context-triggered re-renders

Changes

  • mentionPattern.ts — Generalized buildMentionPattern into buildPrefixPattern(prefix, knownNames) that works for any prefix character
  • remarkChannelLinks.ts — Now accepts channelNames option and uses dynamic pattern matching (like remarkMentions)
  • remarkMentions.ts — Simplified to use shared createRemarkPrefixPlugin factory
  • useChannelLinks.ts — Added multi-word channel name detection in autocomplete (mirroring useMentions)
  • useMentions.ts — Extracted detectMentionQuery into shared detectPrefixQuery
  • markdown.tsx — Passes channel names to plugin, memoizes remarkPlugins array
  • New: createRemarkPrefixPlugin.ts — Shared remark plugin factory
  • New: detectPrefixQuery.ts — Shared prefix query detection for autocomplete

8 files changed, ~234 additions, ~206 deletions (net reduction in duplication)

Test plan

  • Type #channel link highlight in a message — full name should be highlighted, not just #channel
  • Single-word channels like #general still highlight correctly
  • @mention highlighting with multi-word names still works
  • Channel autocomplete suggests multi-word channels as you type
  • # inside code blocks is not highlighted
  • # heading renders as markdown heading, not a channel link

🤖 Generated with Claude Code

wesbillman and others added 3 commits April 3, 2026 14:52
Channel name highlighting previously only matched the first word after #.
This refactors the mention pattern builder into a generic buildPrefixPattern
function shared by both @mention and #channel highlighting, enabling
multi-word channel names to be matched longest-first. Also updates the
composer's channel query detection to scan backwards for # when typing
multi-word names, mirroring the existing @mention behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ix detection

The remark mention/channel-link plugins had identical walkChildren and
split functions, and the useMentions/useChannelLinks hooks had identical
detectQuery functions. Extract createRemarkPrefixPlugin factory and
detectPrefixQuery helper to eliminate ~200 lines of duplication.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rsing

The remarkPlugins array was created inline in JSX on every render, causing
ReactMarkdown to re-parse even when plugin inputs hadn't changed. Wrap it
in useMemo keyed on mentionNames and channelNames.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wesbillman
Copy link
Copy Markdown
Collaborator Author

@codex review please

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: 9e28197bcb

ℹ️ 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 nameAlternatives = sorted.map((name) => escapeRegExp(name)).join("|");
return new RegExp(`@(?:${nameAlternatives}|\\S+)`, "g");
return new RegExp(`${escapedPrefix}(?:${nameAlternatives}|\\S+)`, "g");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add delimiter check after known-name prefix matches

buildPrefixPattern emits #(?:<known>|\S+) without requiring a word/punctuation boundary after a known name, so a shorter existing channel can incorrectly capture the start of a longer token (for example, channel gen makes #general match as #gen). In remarkChannelLinks, that produces a clickable link to the wrong channel and leaves the remaining characters as plain text, which is a functional mis-link introduced by the new name-first matching path.

Useful? React with 👍 / 👎.


const nameAlternatives = sorted.map((name) => escapeRegExp(name)).join("|");
return new RegExp(`@(?:${nameAlternatives}|\\S+)`, "g");
return new RegExp(`${escapedPrefix}(?:${nameAlternatives}|\\S+)`, "g");
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 Make multi-word channel regex case-insensitive

This regex is compiled with only the g flag, so known multi-word channel alternatives are matched case-sensitively. If the channel is Build Team and a user types #build team, the known-name branch will not match and the fallback \S+ branch only captures #build, breaking full multi-word highlighting/linking despite downstream channel lookup being case-insensitive. This creates inconsistent behavior for manually typed links.

Useful? React with 👍 / 👎.

wesbillman and others added 4 commits April 3, 2026 17:35
…fix pattern

Fixes two issues in buildPrefixPattern:
1. Prefix collision: #gen no longer incorrectly matches when typing #general,
   by adding a lookahead requiring a word boundary after known-name matches.
2. Case sensitivity: #build team now correctly matches channel "Build Team"
   by adding the `i` flag for case-insensitive matching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… re-renders

The Markdown component's React.memo comparator checked mentionNames but
not channelNames. Channel names were derived inside MarkdownInner from
useChannelNavigation() context, so when channels loaded async the memo
blocked re-renders and the remark plugin never got real channel names —
falling back to a regex that stopped at spaces.

Move channelNames derivation to each call site (MessageRow,
ForumThreadPanel, ChannelCanvas) and pass it as a prop, mirroring the
existing mentionNames pattern. Add channelNames to the memo comparator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ti-word names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Links hook

Expose knownChannelNames from useChannelLinks so MessageComposer can use it
directly instead of independently deriving channel names from useChannelNavigation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesbillman wesbillman merged commit b1c40ea into main Apr 4, 2026
8 checks passed
@wesbillman wesbillman deleted the fix-channel-highlight-spaces branch April 4, 2026 02:08
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