Changeset 0.23.2 (#155)

This commit is contained in:
2026-03-06 23:17:03 +00:00
parent 4c6555cb06
commit 2dc4514a57
36 changed files with 2784 additions and 192 deletions

View File

@@ -58,35 +58,44 @@ function formatMessage(content) {
function _highlightMentions(html) {
if (typeof ChannelModels === 'undefined') return html;
const roster = ChannelModels.getRoster();
if (!roster || roster.length < 2) return html;
// Build patterns from handles (primary) and display names (fallback)
const patterns = [];
// Build patterns from roster handles and display names (AI mentions)
const aiPatterns = [];
const seen = new Set();
for (const m of roster) {
// Handle pattern (preferred)
if (m.handle) {
const escaped = m.handle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (!seen.has(escaped)) {
patterns.push(new RegExp('(@' + escaped + ')(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
seen.add(escaped);
if (roster && roster.length >= 2) {
for (const m of roster) {
if (m.handle) {
const escaped = m.handle.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (!seen.has(escaped)) {
aiPatterns.push(new RegExp('(@' + escaped + ')(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
seen.add(escaped);
}
}
}
// Display name pattern (hyphenated form)
if (m.display_name) {
const hyphenated = m.display_name.replace(/\s+/g, '-');
const escaped = hyphenated.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (!seen.has(escaped.toLowerCase())) {
const flexible = escaped.replace(/[-]+/g, '[\\s-]+');
patterns.push(new RegExp('(@' + flexible + ')(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
seen.add(escaped.toLowerCase());
if (m.display_name) {
const hyphenated = m.display_name.replace(/\s+/g, '-');
const escaped = hyphenated.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (!seen.has(escaped.toLowerCase())) {
const flexible = escaped.replace(/[-]+/g, '[\\s-]+');
aiPatterns.push(new RegExp('(@' + flexible + ')(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
seen.add(escaped.toLowerCase());
}
}
}
}
// @all
patterns.push(new RegExp('(@all)(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
// @all is special
aiPatterns.push(new RegExp('(@all)(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
// v0.23.2: Build user mention patterns
const userPatterns = [];
for (const u of (App.users || [])) {
const escaped = u.username.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
if (!seen.has(escaped.toLowerCase())) {
userPatterns.push(new RegExp('(@' + escaped + ')(?=[\\s.,!?;:)\\]}<]|$)', 'gi'));
seen.add(escaped.toLowerCase());
}
}
// Don't highlight inside <code>, <pre>, <a> tags
const parts = html.split(/(<[^>]+>)/);
@@ -101,9 +110,14 @@ function _highlightMentions(html) {
}
if (inCode) continue;
let text = part;
for (const re of patterns) {
// AI mentions first (persona/model)
for (const re of aiPatterns) {
text = text.replace(re, '<span class="mention-pill">$1</span>');
}
// User mentions (different color)
for (const re of userPatterns) {
text = text.replace(re, '<span class="mention-pill mention-user">$1</span>');
}
parts[i] = text;
}
return parts.join('');