import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; let source = readFileSync('static/js/mention-autocomplete.js', 'utf8'); source = source.replace(/^import \{ t \} from "@rustpad\/i18n";$/m, 'const t = (key, vars, fallback) => fallback;'); const { mentionAtCaret, filterMentionUsers, normalizeMentionUsers } = await import( 'data:text/javascript;base64,' + Buffer.from(source).toString('base64') ); assert.deepEqual(mentionAtCaret('Cześć @do', 9), { start: 6, end: 9, query: 'do' }); assert.deepEqual(mentionAtCaret('@', 1), { start: 0, end: 1, query: '' }); assert.deepEqual(mentionAtCaret('Pierwsza linia\nWitaj (@Żół', 26), { start: 22, end: 26, query: 'Żół' }); assert.equal(mentionAtCaret('john@example.org', 12), null, 'do not suggest in addresses'); assert.equal(mentionAtCaret('abc@do', 6), null, 'no mention inside a word'); assert.equal(mentionAtCaret('Hello @do ', 10), null, 'space ends a query'); assert.equal(mentionAtCaret('Hello @do-more', 14)?.query, 'do-more', 'support dashes'); assert.equal(mentionAtCaret('Hello @@do', 10), null, 'double at is not a mention'); assert.equal(mentionAtCaret('Hello @do', -1), null); const members = normalizeMentionUsers([ { nickname: 'Dominik', color: '#ff0000', email: 'secret@example.org' }, { nickname: 'DOMINIK', color: '#aaaaaa' }, { nickname: 'Dora', color: 'red' }, { nickname: 'Jan Domański', color: '#00ff00' }, { nickname: '', color: '#00ff00' }, { nickname: 'Joanna', color: '#123abc' }, ]); assert.equal(members.length, 4, 'deduplicate case insensitive, skip empty'); assert.deepEqual(filterMentionUsers(members, 'do').map(user => user.nickname), ['Dominik', 'Dora', 'Jan Domański']); assert.equal(filterMentionUsers(members, 'DO')[0].nickname, 'Dominik'); assert.equal(filterMentionUsers(members, 'zz').length, 0); assert.equal(members[0].color, '#ff0000'); assert.match(members[1].color, /^hsl\(/, 'invalid user color falls back safely'); assert.equal(Object.hasOwn(members[0], 'email'), false, 'no email addresses in UI model'); console.log('PASS: mention context, filtering, normalization, privacy');