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
174 lines
4.3 KiB
TypeScript
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
|
|
}
|