diff --git a/src/modules/chat/tokenizers.js b/src/modules/chat/tokenizers.js index 95a18752..5b5d8088 100644 --- a/src/modules/chat/tokenizers.js +++ b/src/modules/chat/tokenizers.js @@ -328,65 +328,69 @@ export const CheerEmotes = { return tokens; const actions = bitsConfig.indexedActions, - matcher = new RegExp('\\b(' + Object.keys(actions).join('|') + ')(\\d+)\\b', 'ig'); + matcher = new RegExp(`^(${Object.keys(actions).join('|')})(\\d+)$`, 'i'); const out = [], collected = {}, collect = this.context.get('chat.bits.stack'); for(const token of tokens) { - if ( token.type !== 'text' ) { + if ( ! token || token.type !== 'text' ) { out.push(token); continue; } - matcher.lastIndex = 0; - const text = token.text; - let idx = 0, match; + let text = []; + for(const segment of token.text.split(/ +/)) { + const match = matcher.exec(segment); + if ( match ) { + const prefix = match[1].toLowerCase(), + cheer = actions[prefix]; - while((match = matcher.exec(text))) { - const prefix = match[1].toLowerCase(), - cheer = actions[prefix]; - - if ( ! cheer ) - continue; - - if ( idx !== match.index ) - out.push({type: 'text', text: text.slice(idx, match.index)}); - - const amount = parseInt(match[2], 10), - tiers = cheer.orderedTiers; - - let tier, token; - - for(let i=0, l = tiers.length; i < l; i++) - if ( amount >= tiers[i].bits ) { - tier = i; - break; + if ( ! cheer ) { + text.push(segment); + continue; } - out.push(token = { - type: 'cheer', - prefix, - tier, - amount: parseInt(match[2], 10), - text: match[0] - }); + const amount = parseInt(match[2], 10), + tiers = cheer.orderedTiers; - if ( collect ) { - const pref = collect === 2 ? 'cheer' : prefix, - group = collected[pref] = collected[pref] || {total: 0, individuals: []}; + let tier, token; + for(let i=0, l = tiers.length; i < l; i++) + if ( amount >= tiers[i].bits ) { + tier = i; + break; + } - group.total += amount; - group.individuals.push([amount, tier, prefix]); - token.hidden = true; - } + if ( text.length ) { + // We have pending text. Join it together, with an extra space. + out.push({type: 'text', text: `${text.join(' ')} `}); + text = []; + } - idx = match.index + match[0].length; + out.push(token = { + type: 'cheer', + prefix, + tier, + amount, + text: match[0] + }); + + if ( collect ) { + const pref = collect === 2 ? 'cheer' : prefix, + group = collected[pref] = collected[pref] || {total: 0, individuals: []}; + + group.total += amount; + group.individuals.push([amount, tier, prefix]); + token.hidden = true; + } + + } else + text.push(segment); } - if ( idx < text.length ) - out.push({type: 'text', text: text.slice(idx)}); + if ( text.length > 1 || (text.length === 1 && text[0] !== '') ) + out.push({type: 'text', text: text.join(' ')}); } if ( collect ) { diff --git a/src/sites/twitch-twilight/modules/chat/line.js b/src/sites/twitch-twilight/modules/chat/line.js index d7051f02..6ea0ad24 100644 --- a/src/sites/twitch-twilight/modules/chat/line.js +++ b/src/sites/twitch-twilight/modules/chat/line.js @@ -75,7 +75,7 @@ export default class ChatLine extends Module { if ( ! msg.message && msg.messageParts ) detokenizeMessage(msg); - const tokens = msg.ffzTokens = msg.ffzTokens || t.chat.tokenizeMessage(msg, {login: this.props.currentUserLogin, display: this.props.currentUserDisplayName}); + const tokens = msg.ffz_tokens = msg.ffz_tokens || t.chat.tokenizeMessage(msg, {login: this.props.currentUserLogin, display: this.props.currentUserDisplayName}); let cls = 'chat-line__message', out = tokens.length ? [ @@ -175,8 +175,13 @@ export default class ChatLine extends Module { updateLines() { - for(const inst of this.ChatLine.instances) + for(const inst of this.ChatLine.instances) { + const msg = inst.props.message; + if ( msg ) + msg.ffz_tokens = null; + inst.forceUpdate(); + } } }