import { emojiMap } from './emoji' export interface Match { type: 'link' | 'emoji' | 'text' | 'Ait' value: string } const emojiRegExp = new RegExp( '(' + Object.keys(emojiMap) .map((item) => { const left = `\\${item.slice(0, 1)}` const right = `\\${item.slice(-1)}` const mid = item.slice(1, -1) return `${left}${mid}${right}` }) .join('|') + ')', 'g' ) /* eslint-disable vars-on-top, no-var, prefer-template */ // @ts-nocheck var isRegExp = function (re: any) { return re instanceof RegExp } var escapeRegExp = function escapeRegExp(string: string) { var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source) return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, '\\$&') : string } var isString = function (value: string | any[]) { return typeof value === 'string' } var flatten = function (array: any[]) { var newArray: any[] = [] array.forEach(function (item) { if (Array.isArray(item)) { newArray = newArray.concat(item) } else { newArray.push(item) } }) return newArray } /** * Given a string, replace every substring that is matched by the `match` regex * with the result of calling `fn` on matched substring. The result will be an * array with all odd indexed elements containing the replacements. The primary * use case is similar to using String.prototype.replace except for React. * * React will happily render an array as children of a react element, which * makes this approach very useful for tasks like surrounding certain text * within a string with react elements. * * Example: * matchReplace( * 'Emphasize all phone numbers like 884-555-4443.', * /([\d|-]+)/g, * (number, i) => {number} * ); * // => ['Emphasize all phone numbers like ', 884-555-4443, '.' * * @param {string} str * @param {RegExp|str} match Must contain a matching group * @param {function} fn * @return {array} */ function replaceString(str: string | any[], match: RegExp, fn: Function) { var curCharStart = 0 var curCharLen = 0 if (str === '') { return str } else if (!str || !isString(str)) { throw new TypeError( 'First argument to react-string-replace#replaceString must be a string' ) } var re = match if (!isRegExp(re)) { // @ts-ignore re = new RegExp('(' + escapeRegExp(re) + ')', 'gi') } // @ts-ignore var result = str.split(re) // Apply fn to all odd elements for (var i = 1, length = result.length; i < length; i += 2) { /** @see {@link https://github.com/iansinnott/react-string-replace/issues/74} */ if (result[i] === undefined || result[i - 1] === undefined) { console.warn( 'reactStringReplace: Encountered undefined value during string replacement. Your RegExp may not be working the way you expect.' ) continue } curCharLen = result[i].length curCharStart += result[i - 1].length result[i] = fn(result[i], i, curCharStart) curCharStart += curCharLen } return result } // 字符串替换 function stringReplace(source: string | any[], match: RegExp, fn: Function) { if (!Array.isArray(source)) source = [source] return flatten( source.map(function (x) { return isString(x) ? replaceString(x, match, fn) : x }) ) } export function parseText(text: string, ext?: string): Match[] { if (!text) return [] const regexLink = /(https?:\/\/\S+)/gi const yxAitMsg = ext ? JSON.parse(ext).yxAitMsg : null const emojiArr = stringReplace(text, emojiRegExp, (item: any) => { return { type: 'emoji', value: item, } }) const emojiAndLinkArr = stringReplace(emojiArr, regexLink, (item: any) => { return { type: 'link', value: item, } }) let emojiAndLinkAndAitArr = emojiAndLinkArr if (yxAitMsg) { Object.keys(yxAitMsg)?.forEach((key) => { const item = yxAitMsg[key] emojiAndLinkAndAitArr = stringReplace( emojiAndLinkAndAitArr, item.text, (item: any) => { return { type: 'Ait', value: item, } } ) }) } const result = emojiAndLinkAndAitArr.map((item) => { if (typeof item == 'string') { return { type: 'text', value: item, } } else { return item } }) return result }