diff --git a/src/client/app/desktop/views/components/post-form.vue b/src/client/app/desktop/views/components/post-form.vue index 0e86bbf9f..de3e815b8 100644 --- a/src/client/app/desktop/views/components/post-form.vue +++ b/src/client/app/desktop/views/components/post-form.vue @@ -74,6 +74,7 @@ import { host } from '../../../config'; import { erase, unique } from '../../../../../prelude/array'; import { length } from 'stringz'; import { toASCII } from 'punycode'; +import extractMentions from '../../../../../misc/extract-mentions'; export default Vue.extend({ i18n: i18n('desktop/views/components/post-form.vue'), @@ -184,8 +185,7 @@ export default Vue.extend({ if (this.reply && this.reply.text != null) { const ast = parse(this.reply.text); - // TODO: 新しいMFMパーサに対応 - for (const x of ast.filter(t => t.type == 'mention')) { + for (const x of extractMentions(ast)) { const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`; // 自分は除外 diff --git a/src/client/app/mobile/views/components/post-form.vue b/src/client/app/mobile/views/components/post-form.vue index d9cf1471c..e35a64764 100644 --- a/src/client/app/mobile/views/components/post-form.vue +++ b/src/client/app/mobile/views/components/post-form.vue @@ -66,6 +66,7 @@ import { host } from '../../../config'; import { erase, unique } from '../../../../../prelude/array'; import { length } from 'stringz'; import { toASCII } from 'punycode'; +import extractMentions from '../../../../../misc/extract-mentions'; export default Vue.extend({ i18n: i18n('mobile/views/components/post-form.vue'), @@ -174,7 +175,7 @@ export default Vue.extend({ if (this.reply && this.reply.text != null) { const ast = parse(this.reply.text); - for (const x of ast.filter(t => t.type == 'mention')) { + for (const x of extractMentions(ast)) { const mention = x.host ? `@${x.username}@${toASCII(x.host)}` : `@${x.username}`; // 自分は除外 diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts index 6980b36ea..56c49ba3f 100644 --- a/src/mfm/parser.ts +++ b/src/mfm/parser.ts @@ -11,6 +11,15 @@ export type Node = { props?: any; }; +export interface IMentionNode extends Node { + props: { + canonical: string; + username: string; + host: string; + acct: string; + }; +} + function _makeNode(name: string, children?: Node[], props?: any): Node { return children ? { name, diff --git a/src/misc/extract-mentions.ts b/src/misc/extract-mentions.ts new file mode 100644 index 000000000..1d844211c --- /dev/null +++ b/src/misc/extract-mentions.ts @@ -0,0 +1,19 @@ +import parse from '../mfm/parse'; +import { Node, IMentionNode } from '../mfm/parser'; + +export default function(tokens: ReturnType): IMentionNode['props'][] { + const mentions: IMentionNode['props'][] = []; + + const extract = (tokens: Node[]) => { + for (const x of tokens.filter(x => x.name === 'mention')) { + mentions.push(x.props); + } + for (const x of tokens.filter(x => x.children)) { + extract(x.children); + } + }; + + extract(tokens); + + return mentions; +} diff --git a/src/services/note/create.ts b/src/services/note/create.ts index eef36505a..75d9521bd 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -29,6 +29,7 @@ import insertNoteUnread from './unread'; import registerInstance from '../register-instance'; import Instance from '../../models/instance'; import { Node } from '../../mfm/parser'; +import extractMentions from '../../misc/extract-mentions'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; @@ -665,19 +666,7 @@ function incNotesCount(user: IUser) { async function extractMentionedUsers(user: IUser, tokens: ReturnType): Promise { if (tokens == null) return []; - const mentions: any[] = []; - - const extract = (tokens: Node[]) => { - for (const x of tokens.filter(x => x.name === 'mention')) { - mentions.push(x.props); - } - for (const x of tokens.filter(x => x.children)) { - extract(x.children); - } - }; - - // Extract hashtags - extract(tokens); + const mentions = extractMentions(tokens); let mentionedUsers = erase(null, await Promise.all(mentions.map(async m => {