UNPKG

kara-module-file-list

Version:

kara

121 lines (110 loc) 3.25 kB
/** * 对消息按照内容进行切片,切片采用react渲染 * 核心知识点 1正则表达式 2JSX children 3多维数组 * 切片顺序常用功能优先,可以减少数组维度 * 表情 > mention > 引用(换行)> 链接 */ import React, { Component } from 'react'; import css from './index.scss'; import emojiConfig from './EmojiConfig/index'; class PlainMessage extends Component { /** * 切片函数 * @param text 文本 * @param reg 正则 * @param emit 匹配结果转换器 * @param next 余下文本切片 * @returns {*} */ getSlices = (text, reg, emit, next) => { if(!text) { return text } const matchs = text.match(reg); // 匹配的结果 进行相关替换 //console.log('matchs',matchs) if(matchs === null) { // 没有匹配 return next ? next(text) : text; // 没有匹配继续下一个切片 } const slices = text.split(reg); // 切片后的文本 继续下一个切片 //console.log('slice',slices) let items = [] for (let i=0; i<slices.length; i++) { const ele = <span key={i}>{next ? next(slices[i]) : slices[i]}{emit ? emit(matchs[i]): matchs[i]}</span> const children = ele.props.children items = items.concat(children) } return items; } // 高亮解析 getHighLights = (text) => { //console.log('high light 0',text) const reg = /\<span.*?\>.+?\<\/span\>/g return this.getSlices(text, reg, this.getHighLight, this.getEmojis) } getHighLight = (text) => { //console.log('high light 1',text) if(!text) { return null } const reg = /\<span.*\>(.*)\<\/span\>/ const res = text.match(reg) //console.log('high light 2',res) if(res) { return <span className="s-primary">{res[1]}</span> }else{ return text } } // 表情解析 getEmojis = (text) => { const reg = /:\S*?:|\[\S*?\]/g; return this.getSlices(text, reg, this.getEmoji, this.getMentions) } getEmoji = (text) => { // :small: [微笑] for(const i of emojiConfig) { const { size, data } = i if(data[text]) { return <img className={css[size]} src={data[text]} alt='' /> } } return text } // mention @ 解析 getMentions = (text) => { const reg = /<@[^<(?=@)]+?\|.+?>/g; return this.getSlices(text, reg, this.getMention, this.getNewLines) } getMention = (text) => { // <@account|name> if(!text) { return null } const res = /<@([^<(?=@)]+?)\|(.+?)>/g.exec(text); if(!res) { return null } const account = res[1]; const name = res[2]; return account && name ? <span className={css.mention}>@{name === 'all' ? '所有人' : name}</span> : null } // 换行解析 getNewLines = (text) => { const reg = /\n/g; const emit = (t) => { return t ? <br /> : null } return this.getSlices(text, reg, emit) } render() { const { text } = this.props; if(!text) { return null } return ( <p className={css.plain}>{this.getHighLights(text)}</p> ); } } export default PlainMessage;