summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDW <36347199+chocological00@users.noreply.github.com>2020-02-03 18:30:49 -0500
committerGitHub <noreply@github.com>2020-02-04 08:30:49 +0900
commitc110f0860e2ae7bc378c36f8eb6048956ebc3a28 (patch)
tree8d6fc07e3dc1e9a6e7b8ea8b8db18e63f5aa397b /src
parentリモート投稿にリモートでされたリアクションが表示さ... (diff)
downloadsharkey-c110f0860e2ae7bc378c36f8eb6048956ebc3a28.tar.gz
sharkey-c110f0860e2ae7bc378c36f8eb6048956ebc3a28.tar.bz2
sharkey-c110f0860e2ae7bc378c36f8eb6048956ebc3a28.zip
Korean, English Nyaziation and special case exclusion (#5813)
Diffstat (limited to 'src')
-rw-r--r--src/misc/nyaize.ts50
1 files changed, 48 insertions, 2 deletions
diff --git a/src/misc/nyaize.ts b/src/misc/nyaize.ts
index 38c7101766..0b9b83d9af 100644
--- a/src/misc/nyaize.ts
+++ b/src/misc/nyaize.ts
@@ -1,11 +1,57 @@
+import rndstr from 'rndstr';
+
export function nyaize(text: string): string {
- return text
+ const [toNyaize, exclusionMap] = exclude(text);
+ const nyaized = toNyaize
// ja-JP
.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
// en-US
.replace(/morning/gi, 'mornyan').replace(/everyone/gi, 'everynyan')
+ .replace(/o/g, 'owo').replace(/u/g, 'uwu')
// ko-KR
.replace(/[나-낳]/g, match => String.fromCharCode(
- match.codePointAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0)
+ match.charCodeAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0)
+ )).replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥')
+ .replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥');
+ return replaceExceptions(nyaized, exclusionMap);
+}
+
+export function denyaize(text: string): string {
+ return text
+ .replace(/にゃ/g, 'な').replace(/ニャ/g, 'ナ').replace(/ニャ/g, 'ナ')
+ .replace(/owo/g, 'o').replace(/uwu/g, 'u')
+ .replace(/mornyan/gi, 'morning').replace(/everynyan/gi, 'everyone') // this will result in case related bug
+ .replace(/(다냥$)|(다냥(?=\.))|(다냥(?= ))|(다냥(?=!))|(다냥(?=\?))/gm, '다')
+ .replace(/(냥(?=\?))|(냥$)|(냥(?= ))/gm, '야')
+ .replace(/[냐-냫]/g, match => String.fromCharCode(
+ match.charCodeAt(0)! + '나'.charCodeAt(0) - '냐'.charCodeAt(0)
));
}
+
+function exclude(text: string): [string, Record<string, string>] {
+ const map: Record<string, string> = {};
+ function substitute(match: string): string {
+ let randomstr: string;
+ do {
+ randomstr = rndstr({ length: 16, chars: '🀀-🀫' });
+ } while(Object.prototype.hasOwnProperty.call(map, randomstr));
+ map[randomstr] = match;
+ return randomstr;
+ }
+ const replaced = text
+ .replace(/(https?:\/\/.*?)(?= |$)/gm, match => substitute(match)) // URL
+ .replace(/:([a-z0-9_+-]+):/gim, match => substitute(match)) // emoji
+ .replace(/#([^\s.,!?'"#:\/\[\]【】]+)/gm, match => substitute(match)) // hashtag
+ .replace(/@\w([\w-]*\w)?(?:@[\w.\-]+\w)?/gm, match => substitute(match)) // mention
+ .replace(/<\/?[a-zA-Z]*?>/g, match => substitute(match)) // <jump>, <motion>, etc.
+ .replace(/`([^`\n]+?)`/g, match => substitute(match)) // inline code
+ .replace(/```(.+?)?\n([\s\S]+?)```(\n|$)/gm, match => substitute(match)); // code block
+ return [replaced, map];
+}
+
+function replaceExceptions(text: string, map: Record<string, string>): string {
+ for(const rule in map)
+ if(Object.prototype.hasOwnProperty.call(map, rule))
+ text = text.replace(rule, map[rule]);
+ return text;
+} \ No newline at end of file