You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
4.3 KiB
TypeScript

8 months ago
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) => <strong key={i}>{number}</strong>
* );
* // => ['Emphasize all phone numbers like ', <strong>884-555-4443</strong>, '.'
*
* @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
}