mirror of
https://github.com/owncast/owncast.git
synced 2024-12-18 15:23:55 +03:00
72 lines
1.8 KiB
TypeScript
72 lines
1.8 KiB
TypeScript
|
/* eslint-disable class-methods-use-this */
|
||
|
import { ChildrenNode, Matcher, MatchResponse, Node } from 'interweave';
|
||
|
import rewritePattern from 'regexpu-core';
|
||
|
import React from 'react';
|
||
|
|
||
|
export interface ChatMessageEmojiProps {
|
||
|
key: string;
|
||
|
}
|
||
|
|
||
|
interface options {
|
||
|
className: string;
|
||
|
}
|
||
|
|
||
|
const emojiPattern = '\\p{RGI_Emoji}+';
|
||
|
|
||
|
const regexSupportsUnicodeSets = (() => {
|
||
|
// Using a variable for regexpFlags to avoid eslint error about the flag
|
||
|
// being invalid. It's not invalid, it's just new.
|
||
|
const regexpFlags = 'v';
|
||
|
|
||
|
// A bit more working around eslint - just calling new RegExp throws an
|
||
|
// error about not saving the value / just using side effects.
|
||
|
let regexp = null;
|
||
|
try {
|
||
|
regexp = new RegExp(emojiPattern, regexpFlags);
|
||
|
} catch (_) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// We have to use the variable somehow. Since we didn't catch an error
|
||
|
// this line always returns true.
|
||
|
return regexp !== null;
|
||
|
})();
|
||
|
|
||
|
const emojiRegex = (() => {
|
||
|
const rewriteFlags = {
|
||
|
unicodeSetsFlag: regexSupportsUnicodeSets ? 'parse' : 'transform',
|
||
|
};
|
||
|
const regexFlag = regexSupportsUnicodeSets ? 'v' : 'u';
|
||
|
|
||
|
const regexPattern = rewritePattern(emojiPattern, 'v', rewriteFlags);
|
||
|
|
||
|
return new RegExp(regexPattern, regexFlag);
|
||
|
})();
|
||
|
|
||
|
export class ChatMessageEmojiMatcher extends Matcher {
|
||
|
match(str: string): MatchResponse<{}> | null {
|
||
|
const result = str.match(emojiRegex);
|
||
|
|
||
|
if (!result) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
index: result.index!,
|
||
|
length: result[0].length,
|
||
|
match: result[0],
|
||
|
valid: true,
|
||
|
};
|
||
|
}
|
||
|
|
||
|
replaceWith(children: ChildrenNode, props: ChatMessageEmojiProps): Node {
|
||
|
const { key } = props;
|
||
|
const { className } = this.options as options;
|
||
|
return React.createElement('span', { key, className }, children);
|
||
|
}
|
||
|
|
||
|
asTag(): string {
|
||
|
return 'span';
|
||
|
}
|
||
|
}
|