kara-module-file-list
Version:
kara
121 lines (110 loc) • 3.25 kB
JavaScript
/**
* 对消息按照内容进行切片,切片采用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;