MFMをテキストに戻す (#6131)
* Disable Nyaize in quote * mfmを文字列に戻す、nyaizeにmfmを使用 * Revert "Disable Nyaize in quote" This reverts commit 1b238905a5535267d32d7e1aec8afd8bb07b0619. * refactor * use return type as string
This commit is contained in:
		
							parent
							
								
									20ac7e62e9
								
							
						
					
					
						commit
						a471e4b783
					
				
					 3 changed files with 117 additions and 36 deletions
				
			
		
							
								
								
									
										112
									
								
								src/mfm/toString.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/mfm/toString.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,112 @@
 | 
				
			||||||
 | 
					import { MfmForest, MfmTree } from './prelude';
 | 
				
			||||||
 | 
					import { nyaize } from '../misc/nyaize';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type RestoreOptions = {
 | 
				
			||||||
 | 
						doNyaize?: boolean;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function toString(tokens: MfmForest | null, opts?: RestoreOptions): string {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tokens === null) return '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function appendChildren(children: MfmForest, opts?: RestoreOptions): string {
 | 
				
			||||||
 | 
							return children.map(t => handlers[t.node.type](t, opts)).join('');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const handlers: { [key: string]: (token: MfmTree, opts?: RestoreOptions) => string } = {
 | 
				
			||||||
 | 
							bold(token, opts) {
 | 
				
			||||||
 | 
								return `**${appendChildren(token.children, opts)}**`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							big(token, opts) {
 | 
				
			||||||
 | 
								return `***${appendChildren(token.children, opts)}***`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							small(token, opts) {
 | 
				
			||||||
 | 
								return `<small>${appendChildren(token.children, opts)}</small>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							strike(token, opts) {
 | 
				
			||||||
 | 
								return `~~${appendChildren(token.children, opts)}~~`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							italic(token, opts) {
 | 
				
			||||||
 | 
								return `<i>${appendChildren(token.children, opts)}</i>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							motion(token, opts) {
 | 
				
			||||||
 | 
								return `<motion>${appendChildren(token.children, opts)}</motion>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spin(token, opts) {
 | 
				
			||||||
 | 
								return `<spin>${appendChildren(token.children, opts)}</spin>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							jump(token, opts) {
 | 
				
			||||||
 | 
								return `<jump>${appendChildren(token.children, opts)}</jump>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							flip(token, opts) {
 | 
				
			||||||
 | 
								return `<flip>${appendChildren(token.children, opts)}</flip>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							blockCode(token) {
 | 
				
			||||||
 | 
								return `\`\`\`${token.node.props.lang || ''}\n${token.node.props.code}\n\`\`\`\n`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							center(token, opts) {
 | 
				
			||||||
 | 
								return `<center>${appendChildren(token.children, opts)}</center>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							emoji(token) {
 | 
				
			||||||
 | 
								return (token.node.props.emoji ? token.node.props.emoji : `:${token.node.props.name}:`);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hashtag(token) {
 | 
				
			||||||
 | 
								return `#${token.node.props.hashtag}`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							inlineCode(token) {
 | 
				
			||||||
 | 
								return `\`${token.node.props.code}\``;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mathInline(token) {
 | 
				
			||||||
 | 
								return `\\(${token.node.props.formula}\\)`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mathBlock(token) {
 | 
				
			||||||
 | 
								return `\\[${token.node.props.formula}\\]`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							link(token, opts) {
 | 
				
			||||||
 | 
								return `[${appendChildren(token.children, opts)}](${token.node.props.url})`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mention(token) {
 | 
				
			||||||
 | 
								return token.node.props.canonical;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							quote(token) {
 | 
				
			||||||
 | 
								return `${appendChildren(token.children, {doNyaize: false}).replace(/^/gm,'>').trim()}\n`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							title(token, opts) {
 | 
				
			||||||
 | 
								return `[${appendChildren(token.children, opts)}]\n`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							text(token, opts) {
 | 
				
			||||||
 | 
								return (opts && opts.doNyaize) ? nyaize(token.node.props.text) : token.node.props.text;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							url(token) {
 | 
				
			||||||
 | 
								return `<${token.node.props.url}>`;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							search(token, opts) {
 | 
				
			||||||
 | 
								const query = token.node.props.query;
 | 
				
			||||||
 | 
								return `${(opts && opts.doNyaize ? nyaize(query) : query)} [search]\n`;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return appendChildren(tokens, { doNyaize: (opts && opts.doNyaize) || false }).trim();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,5 @@
 | 
				
			||||||
import rndstr from 'rndstr';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function nyaize(text: string): string {
 | 
					export function nyaize(text: string): string {
 | 
				
			||||||
	const [toNyaize, exclusionMap] = exclude(text);
 | 
						return text
 | 
				
			||||||
	const nyaized = toNyaize
 | 
					 | 
				
			||||||
		// ja-JP
 | 
							// ja-JP
 | 
				
			||||||
		.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
 | 
							.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
 | 
				
			||||||
		// en-US
 | 
							// en-US
 | 
				
			||||||
| 
						 | 
					@ -13,34 +10,4 @@ export function nyaize(text: string): string {
 | 
				
			||||||
		))
 | 
							))
 | 
				
			||||||
		.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥')
 | 
							.replace(/(다$)|(다(?=\.))|(다(?= ))|(다(?=!))|(다(?=\?))/gm, '다냥')
 | 
				
			||||||
		.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥');
 | 
							.replace(/(야(?=\?))|(야$)|(야(?= ))/gm, '냥');
 | 
				
			||||||
	return replaceExceptions(nyaized, exclusionMap);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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(/```(.+?)?\n([\s\S]+?)```(\n|$)/gm, match => substitute(match)) // code block
 | 
					 | 
				
			||||||
		.replace(/`([^`\n]+?)`/g, match => substitute(match)) // inline code
 | 
					 | 
				
			||||||
		.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
 | 
					 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
import { EntityRepository, Repository, In } from 'typeorm';
 | 
					import { EntityRepository, Repository, In } from 'typeorm';
 | 
				
			||||||
import { Note } from '../entities/note';
 | 
					import { Note } from '../entities/note';
 | 
				
			||||||
import { User } from '../entities/user';
 | 
					import { User } from '../entities/user';
 | 
				
			||||||
import { nyaize } from '../../misc/nyaize';
 | 
					 | 
				
			||||||
import { Emojis, Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
 | 
					import { Emojis, Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
 | 
				
			||||||
import { ensure } from '../../prelude/ensure';
 | 
					import { ensure } from '../../prelude/ensure';
 | 
				
			||||||
import { SchemaType } from '../../misc/schema';
 | 
					import { SchemaType } from '../../misc/schema';
 | 
				
			||||||
import { awaitAll } from '../../prelude/await-all';
 | 
					import { awaitAll } from '../../prelude/await-all';
 | 
				
			||||||
import { convertLegacyReaction, convertLegacyReactions } from '../../misc/reaction-lib';
 | 
					import { convertLegacyReaction, convertLegacyReactions } from '../../misc/reaction-lib';
 | 
				
			||||||
 | 
					import { toString } from '../../mfm/toString';
 | 
				
			||||||
 | 
					import { parse } from '../../mfm/parse';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type PackedNote = SchemaType<typeof packedNoteSchema>;
 | 
					export type PackedNote = SchemaType<typeof packedNoteSchema>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,7 +218,8 @@ export class NoteRepository extends Repository<Note> {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (packed.user.isCat && packed.text) {
 | 
							if (packed.user.isCat && packed.text) {
 | 
				
			||||||
			packed.text = nyaize(packed.text);
 | 
								const tokens = packed.text ? parse(packed.text) : [];
 | 
				
			||||||
 | 
								packed.text = toString(tokens, { doNyaize: true });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!opts.skipHide) {
 | 
							if (!opts.skipHide) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue