From 428d27a27b0a15e42fcc65f42bf9b4ee61a94367 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 25 Jan 2019 11:01:47 +0900 Subject: [PATCH 01/56] New translations ja-JP.yml (Spanish) --- locales/es-ES.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 0f6a887b0..fe441b255 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -11,7 +11,7 @@ common: about: "Misskey es un Servicio de red social descentralizada de microblogging de código abierto. Contiene una interfaz de usuario altamente personalizable, reacciones a posts, almacenamiento para poder manejar archivos y otras funciones avanzadas. Además de conectarse con la red llamada Fediverso, puede intercambiar mensajes con otras redes sociales. Por ejemplo, si contribuyes con algo, esa contribución es transmitida no sólo a Misskey sino a otras redes sociales. Imagina que se parece a transmitir una onda de radio de un planeta a otro." features: "Características" rich-contents: "Posts" - rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。" + rich-contents-desc: "Escribe sobre tus pensamientos, eventos, todo lo que quieras compartir. Si es necesario, puedes usar varias sintaxis, decorar tus posts y añadir tus imágenes favoritas, archivos de viddeo y encuestas." reaction: "Reacciones" reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。" ui: "Interfaz" From e4601962d0b902a6f7386668b92d840e2733cbb2 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 25 Jan 2019 19:53:11 +0900 Subject: [PATCH 02/56] New translations ja-JP.yml (English) --- locales/en-US.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 91abe2986..87f49dfc5 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -807,8 +807,8 @@ desktop/views/components/settings.vue: timeline: "Timeline" show-my-renotes: "Show my renotes in the timeline" show-renoted-my-notes: "Show renoted posts of mine in timelines" - show-local-renotes: "Show renoted local posts in timelines" - show-maps: "Display a map to show the location" + show-local-renotes: "Show renoted local posts in the timelines" + show-maps: "Display a map to show location" remain-deleted-note: "Continue to show deleted posts" deck-column-align: "Deck column alignment" deck-column-align-center: "Center" From 6bbc6a80b26fd6b65bb34791b93548f32158afbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Sat, 26 Jan 2019 11:26:32 +0900 Subject: [PATCH 03/56] Update style.styl (#3986) --- src/docs/style.styl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/docs/style.styl b/src/docs/style.styl index 4af0f288b..96d14c2b9 100644 --- a/src/docs/style.styl +++ b/src/docs/style.styl @@ -3,6 +3,8 @@ html --primary #fb4e4e + --link #fb4e4e + --linkTapHighlight #fb4e4eb3 body margin 0 From 95d4937e162f19d1ac9dcad8c7fb3ba8124bd448 Mon Sep 17 00:00:00 2001 From: Aya Morisawa Date: Sat, 26 Jan 2019 11:30:30 +0900 Subject: [PATCH 04/56] Remove whiteP and blackP from Reversi (#3736) --- src/games/reversi/core.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/games/reversi/core.ts b/src/games/reversi/core.ts index a198e8dd2..bb27d6f80 100644 --- a/src/games/reversi/core.ts +++ b/src/games/reversi/core.ts @@ -100,20 +100,6 @@ export default class Reversi { return count(WHITE, this.board); } - /** - * 黒石の比率 - */ - public get blackP() { - return this.blackCount == 0 && this.whiteCount == 0 ? 0 : this.blackCount / (this.blackCount + this.whiteCount); - } - - /** - * 白石の比率 - */ - public get whiteP() { - return this.blackCount == 0 && this.whiteCount == 0 ? 0 : this.whiteCount / (this.blackCount + this.whiteCount); - } - public transformPosToXy(pos: number): number[] { const x = pos % this.mapWidth; const y = Math.floor(pos / this.mapWidth); From 5a795c4ab2cbf6d7f656b63a1989d133f1cb3b08 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 26 Jan 2019 16:56:05 +0900 Subject: [PATCH 05/56] =?UTF-8?q?tools/resync-remote-user=20=E3=81=A7=20ex?= =?UTF-8?q?it=20=E3=81=97=E3=81=AA=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=20(?= =?UTF-8?q?#3990)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tools/resync-remote-user.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/resync-remote-user.ts b/src/tools/resync-remote-user.ts index c013de723..4850c768a 100644 --- a/src/tools/resync-remote-user.ts +++ b/src/tools/resync-remote-user.ts @@ -24,9 +24,7 @@ if (!acct.match(/^\w+@\w/)) { console.log(`resync ${acct}`); main(acct).then(() => { - console.log('success'); - process.exit(0); + console.log('Done'); }).catch(e => { console.warn(e); - process.exit(1); }); From da7d1938c968966962606636a400ac941f91d066 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:11:02 +0900 Subject: [PATCH 06/56] [Server] Fix #3991 --- CHANGELOG.md | 1 + src/services/note/create.ts | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7499f32a..824401e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ unreleased * 返信一覧を取得すると非公開投稿も取得されてしまう問題を修正 * メンション一覧を取得すると非公開投稿も取得されてしまう問題を修正 * 通知に非公開投稿が表示される問題を修正 +* ダイレクトで投稿すると100%の確率で表示が二重になる問題を修正 * ウィジットの投稿フォームで投稿するとデフォルトの公開範囲が適用されない問題を修正 10.78.5 diff --git a/src/services/note/create.ts b/src/services/note/create.ts index d3c8699b2..3b5aac8f8 100644 --- a/src/services/note/create.ts +++ b/src/services/note/create.ts @@ -377,8 +377,10 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren if (note.visibility == 'specified') { for (const u of visibleUsers) { - publishHomeTimelineStream(u._id, detailPackedNote); - publishHybridTimelineStream(u._id, detailPackedNote); + if (!u._id.equals(user._id)) { + publishHomeTimelineStream(u._id, detailPackedNote); + publishHybridTimelineStream(u._id, detailPackedNote); + } } } } else { From 85cd6479464c3959b509325be083aa664fb6330d Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 26 Jan 2019 17:14:10 +0900 Subject: [PATCH 07/56] Improve moderation UI (#3989) * admin users UI * tune --- locales/ja-JP.yml | 5 + src/client/app/admin/views/users.user.vue | 82 ++++++++++++ src/client/app/admin/views/users.vue | 154 ++++++++++------------ 3 files changed, 160 insertions(+), 81 deletions(-) create mode 100644 src/client/app/admin/views/users.user.vue diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index bae7a1173..01b1dfa2c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1266,14 +1266,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" diff --git a/src/client/app/admin/views/users.user.vue b/src/client/app/admin/views/users.user.vue new file mode 100644 index 000000000..afece18e8 --- /dev/null +++ b/src/client/app/admin/views/users.user.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/client/app/admin/views/users.vue b/src/client/app/admin/views/users.vue index 6f0f1629f..6b829a2f8 100644 --- a/src/client/app/admin/views/users.vue +++ b/src/client/app/admin/views/users.vue @@ -3,20 +3,26 @@
{{ $t('operation') }}
- + {{ $t('username-or-userid') }} - {{ $t('reset-password') }} - - {{ $t('verify') }} - {{ $t('unverify') }} - - - {{ $t('suspend') }} - {{ $t('unsuspend') }} - {{ $t('lookup') }} - + +
+ +
+ {{ $t('reset-password') }} + + {{ $t('verify') }} + {{ $t('unverify') }} + + + {{ $t('suspend') }} + {{ $t('unsuspend') }} + + +
+
@@ -47,29 +53,7 @@ -
-
- - - -
-
-
- - @{{ user | acct }} - admin - moderator - - -
-
- {{ $t('users.updatedAt') }}: -
-
- {{ $t('users.createdAt') }}: -
-
-
+
{{ $t('@.load-more') }} @@ -83,10 +67,13 @@ import i18n from '../../i18n'; import parseAcct from "../../../../misc/acct/parse"; import { faCertificate, faUsers, faTerminal, faSearch, faKey } from '@fortawesome/free-solid-svg-icons'; import { faSnowflake } from '@fortawesome/free-regular-svg-icons'; +import XUser from './users.user.vue'; export default Vue.extend({ i18n: i18n('admin/views/users.vue'), - + components: { + XUser + }, data() { return { user: null, @@ -131,6 +118,7 @@ export default Vue.extend({ }, methods: { + /** テキストエリアのユーザーを解決する */ async fetchUser() { try { return await this.$root.api('users/show', this.target.startsWith('@') ? parseAcct(this.target) : { userId: this.target }); @@ -149,16 +137,27 @@ export default Vue.extend({ } }, + /** テキストエリアから処理対象ユーザーを設定する */ async showUser() { + this.user = null; const user = await this.fetchUser(); this.$root.api('admin/show-user', { userId: user.id }).then(info => { this.user = info; }); + this.target = ''; + }, + + /** 処理対象ユーザーの情報を更新する */ + async refreshUser() { + this.$root.api('admin/show-user', { userId: this.user._id }).then(info => { + this.user = info; + }); }, async resetPassword() { - const user = await this.fetchUser(); - this.$root.api('admin/reset-password', { userId: user.id }).then(res => { + if (!await this.getConfirmed(this.$t('reset-password-confirm'))) return; + + this.$root.api('admin/reset-password', { userId: this.user._id }).then(res => { this.$root.dialog({ type: 'success', text: this.$t('password-updated', { password: res.password }) @@ -167,11 +166,12 @@ export default Vue.extend({ }, async verifyUser() { + if (!await this.getConfirmed(this.$t('verify-confirm'))) return; + this.verifying = true; const process = async () => { - const user = await this.fetchUser(); - await this.$root.api('admin/verify-user', { userId: user.id }); + await this.$root.api('admin/verify-user', { userId: this.user._id }); this.$root.dialog({ type: 'success', text: this.$t('verified') @@ -186,14 +186,17 @@ export default Vue.extend({ }); this.verifying = false; + + this.refreshUser(); }, async unverifyUser() { + if (!await this.getConfirmed(this.$t('unverify-confirm'))) return; + this.unverifying = true; const process = async () => { - const user = await this.fetchUser(); - await this.$root.api('admin/unverify-user', { userId: user.id }); + await this.$root.api('admin/unverify-user', { userId: this.user._id }); this.$root.dialog({ type: 'success', text: this.$t('unverified') @@ -208,14 +211,17 @@ export default Vue.extend({ }); this.unverifying = false; + + this.refreshUser(); }, async suspendUser() { + if (!await this.getConfirmed(this.$t('suspend-confirm'))) return; + this.suspending = true; const process = async () => { - const user = await this.fetchUser(); - await this.$root.api('admin/suspend-user', { userId: user.id }); + await this.$root.api('admin/suspend-user', { userId: this.user._id }); this.$root.dialog({ type: 'success', text: this.$t('suspended') @@ -230,14 +236,17 @@ export default Vue.extend({ }); this.suspending = false; + + this.refreshUser(); }, async unsuspendUser() { + if (!await this.getConfirmed(this.$t('unsuspend-confirm'))) return; + this.unsuspending = true; const process = async () => { - const user = await this.fetchUser(); - await this.$root.api('admin/unsuspend-user', { userId: user.id }); + await this.$root.api('admin/unsuspend-user', { userId: this.user._id }); this.$root.dialog({ type: 'success', text: this.$t('unsuspended') @@ -252,8 +261,21 @@ export default Vue.extend({ }); this.unsuspending = false; + + this.refreshUser(); }, + async getConfirmed(text: string): Promise { + const confirm = await this.$root.dialog({ + type: 'warning', + showCancelButton: true, + title: 'confirm', + text, + }); + + return !confirm.canceled; + } + fetchUsers() { this.$root.api('admin/show-users', { state: this.state, @@ -277,42 +299,12 @@ export default Vue.extend({ From de1a7b436456b74a70d365dc9e2aebb643d32c75 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:14:43 +0900 Subject: [PATCH 08/56] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 824401e6a..a1ba13339 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ unreleased ---------- * 返信するときにCWを維持するかどうか設定できるように * 外部サービス認証情報の配信 +* 管理画面のモデレーションのUIを強化 * イタリック構文の判定の改善 * テーマが反映されないことがある問題を修正 * ホームにフォロワー限定投稿が表示されない問題を修正 From b3730e3373929a2b82caaca8a7c2de65fc0bf8cf Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:22:36 +0900 Subject: [PATCH 09/56] New translations ja-JP.yml (Catalan) --- locales/ca-ES.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 339a66d0c..25368a4d3 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 821182cad5ebba95a83f6e01f720a64199c3f7b2 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:22:41 +0900 Subject: [PATCH 10/56] New translations ja-JP.yml (Chinese Simplified) --- locales/zh-CN.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index b197f16dc..fafef699c 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "用户不存在" lookup: "订阅" reset-password: "密码重置" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "密码为「{password}」" suspend: "被冻结" + suspend-confirm: "凍結しますか?" suspended: "成功冻结用户" unsuspend: "已解除冻结" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "已成功解除用户冻结" verify: "认证用户" + verify-confirm: "公式アカウントにしますか?" verified: "此账户已被认证" unverify: "解除账户认证" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "该帐户未经认证" users: title: "用户" From 16e4bb7f79af694d2c19609515449a0c816f9ea4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:22:45 +0900 Subject: [PATCH 11/56] New translations ja-JP.yml (English) --- locales/en-US.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/en-US.yml b/locales/en-US.yml index 87f49dfc5..5e48e0d56 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "User not found" lookup: "Look up" reset-password: "Reset password" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "The password is now \"{password}\"" suspend: "Suspend" + suspend-confirm: "凍結しますか?" suspended: "Successfully suspended." unsuspend: "Unsuspend" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "The user has successfully unsuspended." verify: "Verify account" + verify-confirm: "公式アカウントにしますか?" verified: "The account is now being verified" unverify: "Unverify account" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "The account is now being unverified" users: title: "Users" From 6667ddbc26dbdbc5afe797eb9b451433de4b04f1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:22:50 +0900 Subject: [PATCH 12/56] New translations ja-JP.yml (French) --- locales/fr-FR.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index e0216e9a7..5ab41af68 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "Utilisateur non trouvé" lookup: "Recherche" reset-password: "Réinitialiser mot de passe" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "Le mot de passe est « {password} »" suspend: "Suspendre" + suspend-confirm: "凍結しますか?" suspended: "Suspendu avec succès." unsuspend: "Suspension levée" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "La suspension de l’utilisateur a été levée avec succès" verify: "Vérification du compte" + verify-confirm: "公式アカウントにしますか?" verified: "Le compte a été vérifié" unverify: "Enlever la vérification du compte" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "Ce compte n'est plus vérifié" users: title: "Utilisateurs" From 4e92eb55cd2771ea51cbeb71891714ed119bec38 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:22:57 +0900 Subject: [PATCH 13/56] New translations ja-JP.yml (German) --- locales/de-DE.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 225fc70c0..89e545e2f 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 3bffe605f77a32faecc4ec7be99005ccb18cda76 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:02 +0900 Subject: [PATCH 14/56] New translations ja-JP.yml (Italian) --- locales/it-IT.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/it-IT.yml b/locales/it-IT.yml index b826757cc..75729774e 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From db5a4040813cac076124d04df9029bf5b5dcbb8a Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:09 +0900 Subject: [PATCH 15/56] New translations ja-JP.yml (Korean) --- locales/ko-KR.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 70c41d525..2dab99a98 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "사용자를 찾을 수 없습니다" lookup: "조회" reset-password: "암호 재설정" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "암호는 현재 \"{password}\" 입니다" suspend: "정지" + suspend-confirm: "凍結しますか?" suspended: "정지하였습니다" unsuspend: "정지 해제" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "정지를 해제하였습니다" verify: "공식 계정으로 설정" + verify-confirm: "公式アカウントにしますか?" verified: "공식 계정으로 설정하였습니다" unverify: "공식 계정 해제" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "공식 계정을 해제하였습니다" users: title: "사용자" From 9b386fd50ee5a0b863bddb0ce9e030a87cef72ea Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:14 +0900 Subject: [PATCH 16/56] New translations ja-JP.yml (Polish) --- locales/pl-PL.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index d2680194a..5ff7d8d6e 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "Nie znaleziono użytkownika" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "Użytkownicy" From fbfd3a60ed4b154ab82da9b5141e1ba0ed8b4eb1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:18 +0900 Subject: [PATCH 17/56] New translations ja-JP.yml (Portuguese) --- locales/pt-PT.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 61fa70986..17bf49334 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From c9c2e36540acbe7f1184dacaf965c786912b7839 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:22 +0900 Subject: [PATCH 18/56] New translations ja-JP.yml (Russian) --- locales/ru-RU.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 235ae3b3d..4e06bc889 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 9450e567c6a1b999e4062e0f66baa847e3d5b1d7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:27 +0900 Subject: [PATCH 19/56] New translations ja-JP.yml (Spanish) --- locales/es-ES.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/es-ES.yml b/locales/es-ES.yml index fe441b255..1758082b9 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 7c6088b2b458fa84c9c6a69830f1b3132f341325 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:32 +0900 Subject: [PATCH 20/56] New translations ja-JP.yml (Japanese, Kansai) --- locales/ja-KS.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index add497eb9..064d2c523 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つからへん!" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password} 」やで" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 6128e62751f3606dc4dddff6edfab09994ab8d55 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:36 +0900 Subject: [PATCH 21/56] New translations ja-JP.yml (Dutch) --- locales/nl-NL.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 14252b3ef..21d3841cb 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From 1f5e3040ed8eaa18d5e24827d16b0aa1dfa32cd3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:23:40 +0900 Subject: [PATCH 22/56] New translations ja-JP.yml (Norwegian) --- locales/no-NO.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/locales/no-NO.yml b/locales/no-NO.yml index b272f834c..44b3d60a0 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -1134,14 +1134,19 @@ admin/views/users.vue: user-not-found: "ユーザーが見つかりません" lookup: "照会" reset-password: "パスワードをリセット" + reset-password-confirm: "パスワードをリセットしますか?" password-updated: "パスワードは現在「{password}」です" suspend: "凍結" + suspend-confirm: "凍結しますか?" suspended: "凍結しました" unsuspend: "凍結の解除" + unsuspend-confirm: "凍結を解除しますか?" unsuspended: "凍結を解除しました" verify: "公式アカウントにする" + verify-confirm: "公式アカウントにしますか?" verified: "公式アカウントにしました" unverify: "公式アカウントを解除する" + unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" users: title: "ユーザー" From a0f8c7e94ee2de826326a630c783d5c8c39825a7 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:47:56 +0900 Subject: [PATCH 23/56] Resolve #2253 --- CHANGELOG.md | 1 + src/client/app/common/scripts/note-subscriber.ts | 1 + src/services/note/delete.ts | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ba13339..87343664e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ unreleased * 返信するときにCWを維持するかどうか設定できるように * 外部サービス認証情報の配信 * 管理画面のモデレーションのUIを強化 +* 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 * テーマが反映されないことがある問題を修正 * ホームにフォロワー限定投稿が表示されない問題を修正 diff --git a/src/client/app/common/scripts/note-subscriber.ts b/src/client/app/common/scripts/note-subscriber.ts index 9545b5406..c2b4dd6df 100644 --- a/src/client/app/common/scripts/note-subscriber.ts +++ b/src/client/app/common/scripts/note-subscriber.ts @@ -133,6 +133,7 @@ export default prop => ({ case 'deleted': { Vue.set(this.$_ns_target, 'deletedAt', body.deletedAt); + Vue.set(this.$_ns_target, 'renote', null); this.$_ns_target.text = null; this.$_ns_target.tags = []; this.$_ns_target.fileIds = []; diff --git a/src/services/note/delete.ts b/src/services/note/delete.ts index 9709eeaf5..e8ce181d5 100644 --- a/src/services/note/delete.ts +++ b/src/services/note/delete.ts @@ -30,12 +30,25 @@ export default async function(user: IUser, note: INote) { text: null, tags: [], fileIds: [], + renoteId: null, poll: null, geo: null, cw: null } }); + if (note.renoteId) { + Note.update({ _id: note.renoteId }, { + $inc: { + renoteCount: -1, + score: -1 + }, + $pull: { + _quoteIds: note._id + } + }); + } + publishNoteStream(note._id, 'deleted', { deletedAt: deletedAt }); From 0854f2e180be7b2ed4e7ea68d7f45cc156a95627 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 26 Jan 2019 17:53:35 +0900 Subject: [PATCH 24/56] =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=83=AA=E3=83=A2=E3=83=BC=E3=83=88=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E6=83=85=E5=A0=B1=E3=82=92=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=20(#3992)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 2 + src/client/app/admin/views/users.vue | 16 ++++++- src/server/api/common/getters.ts | 42 +++++++++++++++++++ .../api/endpoints/admin/update-remote-user.ts | 36 ++++++++++++++++ 4 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/server/api/endpoints/admin/update-remote-user.ts diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 01b1dfa2c..1735376b2 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1280,6 +1280,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: diff --git a/src/client/app/admin/views/users.vue b/src/client/app/admin/views/users.vue index 6b829a2f8..09d074eee 100644 --- a/src/client/app/admin/views/users.vue +++ b/src/client/app/admin/views/users.vue @@ -20,6 +20,7 @@ {{ $t('suspend') }} {{ $t('unsuspend') }} + {{ $t('update-remote-user') }} @@ -65,7 +66,7 @@ import Vue from 'vue'; import i18n from '../../i18n'; import parseAcct from "../../../../misc/acct/parse"; -import { faCertificate, faUsers, faTerminal, faSearch, faKey } from '@fortawesome/free-solid-svg-icons'; +import { faCertificate, faUsers, faTerminal, faSearch, faKey, faSync } from '@fortawesome/free-solid-svg-icons'; import { faSnowflake } from '@fortawesome/free-regular-svg-icons'; import XUser from './users.user.vue'; @@ -89,7 +90,7 @@ export default Vue.extend({ offset: 0, users: [], existMore: false, - faTerminal, faCertificate, faUsers, faSnowflake, faSearch, faKey + faTerminal, faCertificate, faUsers, faSnowflake, faSearch, faKey, faSync }; }, @@ -265,6 +266,17 @@ export default Vue.extend({ this.refreshUser(); }, + async updateRemoteUser() { + this.$root.api('admin/update-remote-user', { userId: this.user._id }).then(res => { + this.$root.dialog({ + type: 'success', + text: this.$t('remote-user-updated') + }); + }); + + this.refreshUser(); + }, + async getConfirmed(text: string): Promise { const confirm = await this.$root.dialog({ type: 'warning', diff --git a/src/server/api/common/getters.ts b/src/server/api/common/getters.ts index 1fce58b20..1cd054cab 100644 --- a/src/server/api/common/getters.ts +++ b/src/server/api/common/getters.ts @@ -1,5 +1,6 @@ import * as mongo from 'mongodb'; import Note from "../../../models/note"; +import User, { isRemoteUser, isLocalUser } from "../../../models/user"; /** * Get valied note for API processing @@ -16,3 +17,44 @@ export async function getValiedNote(noteId: mongo.ObjectID) { return note; } + +/** + * Get user for API processing + */ +export async function getUser(userId: mongo.ObjectID) { + const user = await User.findOne({ + _id: userId + }); + + if (user == null) { + throw 'user not found'; + } + + return user; +} + +/** + * Get remote user for API processing + */ +export async function getRemoteUser(userId: mongo.ObjectID) { + const user = await getUser(userId); + + if (!isRemoteUser(user)) { + throw 'user is not a remote user'; + } + + return user; +} + +/** + * Get local user for API processing + */ +export async function getLocalUser(userId: mongo.ObjectID) { + const user = await getUser(userId); + + if (!isLocalUser(user)) { + throw 'user is not a local user'; + } + + return user; +} diff --git a/src/server/api/endpoints/admin/update-remote-user.ts b/src/server/api/endpoints/admin/update-remote-user.ts new file mode 100644 index 000000000..9288ce1fb --- /dev/null +++ b/src/server/api/endpoints/admin/update-remote-user.ts @@ -0,0 +1,36 @@ +import * as mongo from 'mongodb'; +import $ from 'cafy'; +import ID, { transform } from '../../../../misc/cafy-id'; +import define from '../../define'; +import { getRemoteUser } from '../../common/getters'; +import { updatePerson } from '../../../../remote/activitypub/models/person'; + +export const meta = { + desc: { + 'ja-JP': '指定されたリモートユーザーの情報を更新します。', + 'en-US': 'Update specified remote user information.' + }, + + requireCredential: true, + requireModerator: true, + + params: { + userId: { + validator: $.type(ID), + transform: transform, + desc: { + 'ja-JP': '対象のユーザーID', + 'en-US': 'The user ID which you want to update' + } + }, + } +}; + +export default define(meta, (ps) => new Promise((res, rej) => { + updatePersonById(ps.userId).then(() => res(), e => rej(e)); +})); + +async function updatePersonById(userId: mongo.ObjectID) { + const user = await getRemoteUser(userId); + await updatePerson(user.uri); +} From 6f6974a6ae9177acdb1bfdc6f19f3a6f36b3999b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 17:54:00 +0900 Subject: [PATCH 25/56] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87343664e..b06c3f63c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ unreleased * 返信するときにCWを維持するかどうか設定できるように * 外部サービス認証情報の配信 * 管理画面のモデレーションのUIを強化 +* 管理画面からリモートユーザーの情報を更新できるように * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 * テーマが反映されないことがある問題を修正 From d717b1d4043866d67395a31c15bc7c739af72ba0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:02:59 +0900 Subject: [PATCH 26/56] New translations ja-JP.yml (Catalan) --- locales/ca-ES.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 25368a4d3..3901a4e90 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From e5fcb2aea027d6177349d8df4ba93b454189dbbc Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:03 +0900 Subject: [PATCH 27/56] New translations ja-JP.yml (Chinese Simplified) --- locales/zh-CN.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index fafef699c..a93b8c798 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "解除账户认证" unverify-confirm: "公式アカウントを解除しますか?" unverified: "该帐户未经认证" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "用户" sort: From 5eeec0becb1a596dc2b6f8375c583c770748411b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:08 +0900 Subject: [PATCH 28/56] New translations ja-JP.yml (English) --- locales/en-US.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/en-US.yml b/locales/en-US.yml index 5e48e0d56..615f3ba22 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "Unverify account" unverify-confirm: "公式アカウントを解除しますか?" unverified: "The account is now being unverified" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "Users" sort: From 456b01590b9c15c07d75380055d18dff2a94c830 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:13 +0900 Subject: [PATCH 29/56] New translations ja-JP.yml (French) --- locales/fr-FR.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 5ab41af68..cf3ab8fc7 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "Enlever la vérification du compte" unverify-confirm: "公式アカウントを解除しますか?" unverified: "Ce compte n'est plus vérifié" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "Utilisateurs" sort: From bf00b59339a1bd5569d0eaf2436e9bf1663b50f6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:17 +0900 Subject: [PATCH 30/56] New translations ja-JP.yml (German) --- locales/de-DE.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 89e545e2f..0be4b072b 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From ec50240a03e9b4cb092c7126c6d028292b93c4a1 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:21 +0900 Subject: [PATCH 31/56] New translations ja-JP.yml (Italian) --- locales/it-IT.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 75729774e..92a3ec84c 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From ff2fc2267d3b5b9e0fb867300a44290cec68f671 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:26 +0900 Subject: [PATCH 32/56] New translations ja-JP.yml (Korean) --- locales/ko-KR.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 2dab99a98..bb04a67d0 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "공식 계정 해제" unverify-confirm: "公式アカウントを解除しますか?" unverified: "공식 계정을 해제하였습니다" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "사용자" sort: From 990bc976de95de6f9614c995ad9777b00d3d5567 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:30 +0900 Subject: [PATCH 33/56] New translations ja-JP.yml (Polish) --- locales/pl-PL.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 5ff7d8d6e..ec1c6214e 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "Użytkownicy" sort: From 3781f07c49bfbaee0c4c99955bf00ba0c440e2f0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:35 +0900 Subject: [PATCH 34/56] New translations ja-JP.yml (Portuguese) --- locales/pt-PT.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 17bf49334..27549d3f7 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From a82eeb7e9259111be603d833b4f9d61ae95a9fc0 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:39 +0900 Subject: [PATCH 35/56] New translations ja-JP.yml (Russian) --- locales/ru-RU.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index 4e06bc889..2f7980dcb 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From a45abf858fe30d7a5b123bac8996e36416c321ac Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:45 +0900 Subject: [PATCH 36/56] New translations ja-JP.yml (Spanish) --- locales/es-ES.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 1758082b9..8ace707e5 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From a83c3557fce0261c93effed5fc9d6e8c93a5614a Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:50 +0900 Subject: [PATCH 37/56] New translations ja-JP.yml (Japanese, Kansai) --- locales/ja-KS.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 064d2c523..d3270f1aa 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From b8f60527f614a1199282017c4559b920c3190cb8 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:03:57 +0900 Subject: [PATCH 38/56] New translations ja-JP.yml (Dutch) --- locales/nl-NL.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 21d3841cb..d6f2c8789 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From 3ab5d2e0e1bae6b6420e58227516de2566fd1c3d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 18:04:03 +0900 Subject: [PATCH 39/56] New translations ja-JP.yml (Norwegian) --- locales/no-NO.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/locales/no-NO.yml b/locales/no-NO.yml index 44b3d60a0..ffade4a24 100644 --- a/locales/no-NO.yml +++ b/locales/no-NO.yml @@ -1148,6 +1148,8 @@ admin/views/users.vue: unverify: "公式アカウントを解除する" unverify-confirm: "公式アカウントを解除しますか?" unverified: "公式アカウントを解除しました" + update-remote-user: "リモートユーザー情報の更新" + remote-user-updated: "リモートユーザー情報を更新しました" users: title: "ユーザー" sort: From f9e6c84d00c2506439149e0cdfe82aa75f9c7582 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 19:22:23 +0900 Subject: [PATCH 40/56] New translations ja-JP.yml (English) --- locales/en-US.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 615f3ba22..90f191157 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1134,22 +1134,22 @@ admin/views/users.vue: user-not-found: "User not found" lookup: "Look up" reset-password: "Reset password" - reset-password-confirm: "パスワードをリセットしますか?" + reset-password-confirm: "Do you want to reset your password?" password-updated: "The password is now \"{password}\"" suspend: "Suspend" - suspend-confirm: "凍結しますか?" + suspend-confirm: "Do you want to suspend this account?" suspended: "Successfully suspended." unsuspend: "Unsuspend" - unsuspend-confirm: "凍結を解除しますか?" + unsuspend-confirm: "Are you sure you want to unsuspend this account?" unsuspended: "The user has successfully unsuspended." verify: "Verify account" - verify-confirm: "公式アカウントにしますか?" + verify-confirm: "Do you want this to be a verified account?" verified: "The account is now being verified" unverify: "Unverify account" - unverify-confirm: "公式アカウントを解除しますか?" + unverify-confirm: "Do you want to remove the 'verified account' designation?" unverified: "The account is now being unverified" - update-remote-user: "リモートユーザー情報の更新" - remote-user-updated: "リモートユーザー情報を更新しました" + update-remote-user: "Update information about remote user" + remote-user-updated: "The information regarding the remote user has been updated." users: title: "Users" sort: From 5ae576bad1cec2c7430864422260784503bd33e9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 26 Jan 2019 20:59:14 +0900 Subject: [PATCH 41/56] :art: --- .../choose-file-from-drive-window.vue | 189 +++++++----------- .../choose-folder-from-drive-window.vue | 104 +++------- 2 files changed, 92 insertions(+), 201 deletions(-) diff --git a/src/client/app/desktop/views/components/choose-file-from-drive-window.vue b/src/client/app/desktop/views/components/choose-file-from-drive-window.vue index 8aa7fe167..7c69f3aa7 100644 --- a/src/client/app/desktop/views/components/choose-file-from-drive-window.vue +++ b/src/client/app/desktop/views/components/choose-file-from-drive-window.vue @@ -1,21 +1,23 @@ @@ -60,120 +62,67 @@ export default Vue.extend({ }); - diff --git a/src/client/app/desktop/views/components/choose-folder-from-drive-window.vue b/src/client/app/desktop/views/components/choose-folder-from-drive-window.vue index e5ea7bea1..8633b86e4 100644 --- a/src/client/app/desktop/views/components/choose-folder-from-drive-window.vue +++ b/src/client/app/desktop/views/components/choose-folder-from-drive-window.vue @@ -1,17 +1,19 @@ @@ -36,79 +38,19 @@ export default Vue.extend({ }); - From 94154a1aa29a85714bc9334bfb7d380059a34a59 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sat, 26 Jan 2019 21:10:25 +0900 Subject: [PATCH 42/56] =?UTF-8?q?=E3=83=86=E3=83=BC=E3=83=9E=E3=81=AB?= =?UTF-8?q?=E3=82=88=E3=81=A3=E3=81=A6=E3=82=B3=E3=83=BC=E3=83=89=E3=81=8C?= =?UTF-8?q?=E8=A6=8B=E3=81=A5=E3=82=89=E3=81=84=E3=81=AE=E3=82=92=E5=B0=91?= =?UTF-8?q?=E3=81=97=E6=94=B9=E5=96=84=20(#3993)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/common/views/components/misskey-flavored-markdown.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.vue b/src/client/app/common/views/components/misskey-flavored-markdown.vue index 6fc2aa795..33e3679d4 100644 --- a/src/client/app/common/views/components/misskey-flavored-markdown.vue +++ b/src/client/app/common/views/components/misskey-flavored-markdown.vue @@ -36,9 +36,9 @@ export default Vue.extend({ >>> code padding 4px 8px margin 0 0.5em - font-size 80% + font-size 90% color #525252 - background rgba(0, 0, 0, 0.05) + background var(--bg) border-radius 2px >>> pre > code From be5714a9f1993356dff909b3f218756fb3c028e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Sun, 27 Jan 2019 12:36:47 +0900 Subject: [PATCH 43/56] Update qrcode requirement from 1.3.2 to 1.3.3 (#3988) Updates the requirements on [qrcode](https://github.com/soldair/node-qrcode) to permit the latest version. - [Release notes](https://github.com/soldair/node-qrcode/releases) - [Changelog](https://github.com/soldair/node-qrcode/blob/master/CHANGELOG.md) - [Commits](https://github.com/soldair/node-qrcode/commits/v1.3.3) Signed-off-by: dependabot[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f7c704fb..d5afc934b 100644 --- a/package.json +++ b/package.json @@ -184,7 +184,7 @@ "promise-sequential": "1.1.1", "pug": "2.0.3", "punycode": "2.1.1", - "qrcode": "1.3.2", + "qrcode": "1.3.3", "randomcolor": "0.5.3", "ratelimiter": "3.2.0", "recaptcha-promise": "0.1.3", From 895e80d7946b824cd806b5257cf8e812c8e4d5d2 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 13:11:47 +0900 Subject: [PATCH 44/56] New translations ja-JP.yml (French) --- locales/fr-FR.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index cf3ab8fc7..c097872de 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -788,7 +788,7 @@ desktop/views/components/settings.vue: auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" deck-nav: "Deck sans tansitions" deck-nav-desc: "Vous obtenez une colonne temporaire sans transitions dans la page pendant la navigation, lors de l’utilisation du Deck." - keep-cw: "CW保持" + keep-cw: "Maintenir l'avertissement de contenu" keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。" deck-default: "Utiliser le Deck comme IU par défaut" display: "Affichage et design" @@ -1137,19 +1137,19 @@ admin/views/users.vue: reset-password-confirm: "パスワードをリセットしますか?" password-updated: "Le mot de passe est « {password} »" suspend: "Suspendre" - suspend-confirm: "凍結しますか?" + suspend-confirm: "Désirez-vous suspendre ce compte ?" suspended: "Suspendu avec succès." unsuspend: "Suspension levée" - unsuspend-confirm: "凍結を解除しますか?" + unsuspend-confirm: "Souhaiteriez-vous ne plus suspendre ce compte ?" unsuspended: "La suspension de l’utilisateur a été levée avec succès" verify: "Vérification du compte" - verify-confirm: "公式アカウントにしますか?" + verify-confirm: "Souhaiteriez-vous rendre votre compte comme étant un compte vérifié ?" verified: "Le compte a été vérifié" unverify: "Enlever la vérification du compte" unverify-confirm: "公式アカウントを解除しますか?" unverified: "Ce compte n'est plus vérifié" - update-remote-user: "リモートユーザー情報の更新" - remote-user-updated: "リモートユーザー情報を更新しました" + update-remote-user: "Mettre à jour les informations de l’utilisateur·rice distant·e" + remote-user-updated: "Les informations de l’utilisateur·rice distant·e ont étés mis à jour" users: title: "Utilisateurs" sort: @@ -1476,7 +1476,7 @@ mobile/views/pages/settings.vue: notification-position-top: "en haut" behavior: "Comportement" fetch-on-scroll: "Chargement lors du défilement" - keep-cw: "CW保持" + keep-cw: "Garder l'avertissement de contenu" note-visibility: "Visibilité de la publication" default-note-visibility: "Visibilité par défaut" remember-note-visibility: "Se souvenir du mode de visibilité de la publication" From 7dcea49be74784132469e027845fc68557aa8dd4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 13:29:53 +0900 Subject: [PATCH 45/56] Refactoring --- locales/ja-JP.yml | 12 +-- .../views/components/media-image.vue | 12 ++- .../common/views/components/media-list.vue | 6 +- .../app/desktop/views/components/index.ts | 2 - .../desktop/views/components/media-image.vue | 81 ------------------- .../app/mobile/views/components/index.ts | 2 - 6 files changed, 17 insertions(+), 98 deletions(-) rename src/client/app/{mobile => common}/views/components/media-image.vue (84%) delete mode 100644 src/client/app/desktop/views/components/media-image.vue diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1735376b2..91a6add5d 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -730,10 +730,6 @@ desktop/views/components/drive.vue: upload: "ファイルをアップロード" url-upload: "URLからアップロード" -desktop/views/components/media-image.vue: - sensitive: "閲覧注意" - click-to-show: "クリックして表示" - desktop/views/components/media-video.vue: sensitive: "閲覧注意" click-to-show: "クリックして表示" @@ -980,6 +976,10 @@ desktop/views/components/settings.2fa.vue: failed: "設定に失敗しました。トークンに誤りがないかご確認ください。" info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。" +common/views/components/media-image.vue: + sensitive: "閲覧注意" + click-to-show: "クリックして表示" + common/views/components/api-settings.vue: intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。" caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。" @@ -1493,10 +1493,6 @@ mobile/views/components/drive.file-detail.vue: mark-as-sensitive: "閲覧注意に設定" unmark-as-sensitive: "閲覧注意を解除" -mobile/views/components/media-image.vue: - sensitive: "閲覧注意" - click-to-show: "クリックして表示" - mobile/views/components/media-video.vue: sensitive: "閲覧注意" click-to-show: "クリックして表示" diff --git a/src/client/app/mobile/views/components/media-image.vue b/src/client/app/common/views/components/media-image.vue similarity index 84% rename from src/client/app/mobile/views/components/media-image.vue rename to src/client/app/common/views/components/media-image.vue index dbb275b51..01187465f 100644 --- a/src/client/app/mobile/views/components/media-image.vue +++ b/src/client/app/common/views/components/media-image.vue @@ -5,16 +5,21 @@ {{ $t('click-to-show') }} - + - - diff --git a/src/client/app/mobile/views/components/index.ts b/src/client/app/mobile/views/components/index.ts index 9a410e827..351aaea9f 100644 --- a/src/client/app/mobile/views/components/index.ts +++ b/src/client/app/mobile/views/components/index.ts @@ -3,7 +3,6 @@ import Vue from 'vue'; import ui from './ui.vue'; import note from './note.vue'; import notes from './notes.vue'; -import mediaImage from './media-image.vue'; import mediaVideo from './media-video.vue'; import notePreview from './note-preview.vue'; import subNoteContent from './sub-note-content.vue'; @@ -24,7 +23,6 @@ import postForm from './post-form.vue'; Vue.component('mk-ui', ui); Vue.component('mk-note', note); Vue.component('mk-notes', notes); -Vue.component('mk-media-image', mediaImage); Vue.component('mk-media-video', mediaVideo); Vue.component('mk-note-preview', notePreview); Vue.component('mk-sub-note-content', subNoteContent); From 085325e65fa47c9dd9f2d261faeb7775f9f2486f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 13:40:38 +0900 Subject: [PATCH 46/56] [MFM] Improve title syntax detection --- CHANGELOG.md | 1 + src/mfm/parser.ts | 1 + test/mfm.ts | 7 +++++++ 3 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b06c3f63c..6325663fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ unreleased * 管理画面からリモートユーザーの情報を更新できるように * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 +* タイトル構文の判定の改善 * テーマが反映されないことがある問題を修正 * ホームにフォロワー限定投稿が表示されない問題を修正 * 返信一覧を取得すると非公開投稿も取得されてしまう問題を修正 diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts index b86e1d555..5572e26f8 100644 --- a/src/mfm/parser.ts +++ b/src/mfm/parser.ts @@ -361,6 +361,7 @@ const mfm = P.createLanguage({ const match = text.match(/^((【|\[)(.+?)(】|]))(\n|$)/); if (!match) return P.makeFailure(i, 'not a title'); const q = match[1].trim().substring(1, match[1].length - 1); + if (q.includes('】')) return P.makeFailure(i, 'not a title'); const contents = P.alt( r.big, r.small, diff --git a/test/mfm.ts b/test/mfm.ts index a4b4a1397..2124f592f 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -894,6 +894,13 @@ describe('MFM', () => { text('after') ]); }); + + it('ignore multiple title blocks', () => { + const tokens = analyze('【foo】bar【baz】'); + assert.deepStrictEqual(tokens, [ + text('【foo】bar【baz】') + ]); + }); }); describe('center', () => { From 71210595d2fade60c6f84041402d5627ac700928 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 13:48:56 +0900 Subject: [PATCH 47/56] [Test] Add a MFM test --- test/mfm.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/mfm.ts b/test/mfm.ts index 2124f592f..8eadfc728 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -901,6 +901,13 @@ describe('MFM', () => { text('【foo】bar【baz】') ]); }); + + it('disallow linebreak in title', () => { + const tokens = analyze('【foo\nbar】'); + assert.deepStrictEqual(tokens, [ + text('【foo\nbar】') + ]); + }); }); describe('center', () => { From 54ce19bd567504c029e60f7baddd53ffd8bfcbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Sun, 27 Jan 2019 13:50:47 +0900 Subject: [PATCH 48/56] Update parser.ts (#3999) * Update parser.ts * Update parser.ts * Update parser.ts --- src/mfm/parser.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts index 5572e26f8..560e226af 100644 --- a/src/mfm/parser.ts +++ b/src/mfm/parser.ts @@ -358,10 +358,9 @@ const mfm = P.createLanguage({ title: r => newline.then(P((input, i) => { const text = input.substr(i); - const match = text.match(/^((【|\[)(.+?)(】|]))(\n|$)/); + const match = text.match(/^([【\[]([^【\[】\]\n]+?)[】\]])(\n|$)/); if (!match) return P.makeFailure(i, 'not a title'); - const q = match[1].trim().substring(1, match[1].length - 1); - if (q.includes('】')) return P.makeFailure(i, 'not a title'); + const q = match[2].trim(); const contents = P.alt( r.big, r.small, From 50b809784fca1b9933fd8b1ef766228c959b5c45 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 13:55:11 +0900 Subject: [PATCH 49/56] Improve readability and some cleanups --- test/mfm.ts | 87 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 20 deletions(-) diff --git a/test/mfm.ts b/test/mfm.ts index 8eadfc728..a5ea4b293 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -152,9 +152,19 @@ describe('MFM', () => { it('can be analyzed', () => { const tokens = analyze('@himawari @hima_sub@namori.net お腹ペコい :cat: #yryr'); assert.deepStrictEqual(tokens, [ - leaf('mention', { acct: '@himawari', canonical: '@himawari', username: 'himawari', host: null }), + leaf('mention', { + acct: '@himawari', + canonical: '@himawari', + username: 'himawari', + host: null + }), text(' '), - leaf('mention', { acct: '@hima_sub@namori.net', canonical: '@hima_sub@namori.net', username: 'hima_sub', host: 'namori.net' }), + leaf('mention', { + acct: '@hima_sub@namori.net', + canonical: '@hima_sub@namori.net', + username: 'hima_sub', + host: 'namori.net' + }), text(' お腹ペコい '), leaf('emoji', { name: 'cat' }), text(' '), @@ -280,7 +290,12 @@ describe('MFM', () => { it('local', () => { const tokens = analyze('@himawari foo'); assert.deepStrictEqual(tokens, [ - leaf('mention', { acct: '@himawari', canonical: '@himawari', username: 'himawari', host: null }), + leaf('mention', { + acct: '@himawari', + canonical: '@himawari', + username: 'himawari', + host: null + }), text(' foo') ]); }); @@ -288,7 +303,12 @@ describe('MFM', () => { it('remote', () => { const tokens = analyze('@hima_sub@namori.net foo'); assert.deepStrictEqual(tokens, [ - leaf('mention', { acct: '@hima_sub@namori.net', canonical: '@hima_sub@namori.net', username: 'hima_sub', host: 'namori.net' }), + leaf('mention', { + acct: '@hima_sub@namori.net', + canonical: '@hima_sub@namori.net', + username: 'hima_sub', + host: 'namori.net' + }), text(' foo') ]); }); @@ -296,7 +316,12 @@ describe('MFM', () => { it('remote punycode', () => { const tokens = analyze('@hima_sub@xn--q9j5bya.xn--zckzah foo'); assert.deepStrictEqual(tokens, [ - leaf('mention', { acct: '@hima_sub@xn--q9j5bya.xn--zckzah', canonical: '@hima_sub@なもり.テスト', username: 'hima_sub', host: 'xn--q9j5bya.xn--zckzah' }), + leaf('mention', { + acct: '@hima_sub@xn--q9j5bya.xn--zckzah', + canonical: '@hima_sub@なもり.テスト', + username: 'hima_sub', + host: 'xn--q9j5bya.xn--zckzah' + }), text(' foo') ]); }); @@ -309,11 +334,26 @@ describe('MFM', () => { const tokens2 = analyze('@a\n@b\n@c'); assert.deepStrictEqual(tokens2, [ - leaf('mention', { acct: '@a', canonical: '@a', username: 'a', host: null }), + leaf('mention', { + acct: '@a', + canonical: '@a', + username: 'a', + host: null + }), text('\n'), - leaf('mention', { acct: '@b', canonical: '@b', username: 'b', host: null }), + leaf('mention', { + acct: '@b', + canonical: '@b', + username: 'b', + host: null + }), text('\n'), - leaf('mention', { acct: '@c', canonical: '@c', username: 'c', host: null }) + leaf('mention', { + acct: '@c', + canonical: '@c', + username: 'c', + host: null + }) ]); const tokens3 = analyze('**x**@a'); @@ -321,24 +361,31 @@ describe('MFM', () => { tree('bold', [ text('x') ], {}), - leaf('mention', { acct: '@a', canonical: '@a', username: 'a', host: null }) + leaf('mention', { + acct: '@a', + canonical: '@a', + username: 'a', + host: null + }) ]); - const tokens4 = analyze('@\n@v\n@veryverylongusername' /* \n@toolongtobeasamention */); + const tokens4 = analyze('@\n@v\n@veryverylongusername'); assert.deepStrictEqual(tokens4, [ text('@\n'), - leaf('mention', { acct: '@v', canonical: '@v', username: 'v', host: null }), + leaf('mention', { + acct: '@v', + canonical: '@v', + username: 'v', + host: null + }), text('\n'), - leaf('mention', { acct: '@veryverylongusername', canonical: '@veryverylongusername', username: 'veryverylongusername', host: null }), - // text('\n@toolongtobeasamention') + leaf('mention', { + acct: '@veryverylongusername', + canonical: '@veryverylongusername', + username: 'veryverylongusername', + host: null + }), ]); - /* - const tokens5 = analyze('@domain_is@valid.example.com\n@domain_is@.invalid\n@domain_is@invali.d\n@domain_is@invali.d\n@domain_is@-invalid.com\n@domain_is@invalid-.com'); - assert.deepStrictEqual([ - leaf('mention', { acct: '@domain_is@valid.example.com', canonical: '@domain_is@valid.example.com', username: 'domain_is', host: 'valid.example.com' }), - text('\n@domain_is@.invalid\n@domain_is@invali.d\n@domain_is@invali.d\n@domain_is@-invalid.com\n@domain_is@invalid-.com') - ], tokens5); - */ }); }); From f9f70d5df45da43d88c2fe51ce3da4b414ac014b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 14:30:57 +0900 Subject: [PATCH 50/56] Clean up --- .../views/components/misskey-flavored-markdown.vue | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.vue b/src/client/app/common/views/components/misskey-flavored-markdown.vue index 33e3679d4..448df9aa8 100644 --- a/src/client/app/common/views/components/misskey-flavored-markdown.vue +++ b/src/client/app/common/views/components/misskey-flavored-markdown.vue @@ -45,13 +45,4 @@ export default Vue.extend({ padding 16px margin 0 - >>> [data-is-me]:after - content "you" - padding 0 4px - margin-left 4px - font-size 80% - color var(--primaryForeground) - background var(--primary) - border-radius 4px - From 4b191c7f68a13e1a9acb00b8b8c1b7638465f5f5 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 14:34:52 +0900 Subject: [PATCH 51/56] [Client] Improve syntax highlighting Resolve #3926 Resolve #3390 --- CHANGELOG.md | 1 + package.json | 4 +- .../app/common/views/components/code-core.vue | 30 ++ .../app/common/views/components/code.vue | 28 ++ src/client/app/common/views/components/mfm.ts | 27 +- .../components/misskey-flavored-markdown.vue | 15 - src/mfm/syntax-highlight.ts | 343 ------------------ 7 files changed, 76 insertions(+), 372 deletions(-) create mode 100644 src/client/app/common/views/components/code-core.vue create mode 100644 src/client/app/common/views/components/code.vue delete mode 100644 src/mfm/syntax-highlight.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6325663fc..d9e69e8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ unreleased * 外部サービス認証情報の配信 * 管理画面のモデレーションのUIを強化 * 管理画面からリモートユーザーの情報を更新できるように +* シンタックスハイライトの強化 * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 * タイトル構文の判定の改善 diff --git a/package.json b/package.json index d5afc934b..b561b4de4 100644 --- a/package.json +++ b/package.json @@ -97,8 +97,8 @@ "bootstrap-vue": "2.0.0-rc.11", "cafy": "12.0.0", "chai": "4.2.0", - "chalk": "2.4.2", "chai-http": "4.2.1", + "chalk": "2.4.2", "commander": "2.19.0", "crc-32": "1.2.0", "css-loader": "1.0.1", @@ -178,6 +178,7 @@ "parsimmon": "1.12.0", "portscanner": "2.2.0", "postcss-loader": "3.0.0", + "prismjs": "1.15.0", "progress-bar-webpack-plugin": "1.12.0", "promise-any": "0.2.0", "promise-limit": "2.7.0", @@ -230,6 +231,7 @@ "vue-js-modal": "1.3.28", "vue-loader": "15.5.1", "vue-marquee-text-component": "1.1.1", + "vue-prism-component": "1.1.1", "vue-router": "3.0.2", "vue-sequential-entrance": "1.1.3", "vue-style-loader": "4.1.2", diff --git a/src/client/app/common/views/components/code-core.vue b/src/client/app/common/views/components/code-core.vue new file mode 100644 index 000000000..a50d94394 --- /dev/null +++ b/src/client/app/common/views/components/code-core.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/client/app/common/views/components/code.vue b/src/client/app/common/views/components/code.vue new file mode 100644 index 000000000..d52c9f7bc --- /dev/null +++ b/src/client/app/common/views/components/code.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/client/app/common/views/components/mfm.ts b/src/client/app/common/views/components/mfm.ts index ad3d8204c..8ffa56666 100644 --- a/src/client/app/common/views/components/mfm.ts +++ b/src/client/app/common/views/components/mfm.ts @@ -6,8 +6,8 @@ import MkUrl from './url.vue'; import MkMention from './mention.vue'; import { concat, sum } from '../../../../../prelude/array'; import MkFormula from './formula.vue'; +import MkCode from './code.vue'; import MkGoogle from './google.vue'; -import syntaxHighlight from '../../../../../mfm/syntax-highlight'; import { host } from '../../../config'; import { preorderF, countNodesF } from '../../../../../prelude/tree'; @@ -170,21 +170,22 @@ export default Vue.component('misskey-flavored-markdown', { } case 'blockCode': { - return [createElement('pre', { - class: 'code' - }, [ - createElement('code', { - domProps: { - innerHTML: syntaxHighlight(token.node.props.code) - } - }) - ])]; + return [createElement(MkCode, { + key: Math.random(), + props: { + code: token.node.props.code, + lang: token.node.props.lang, + } + })]; } case 'inlineCode': { - return [createElement('code', { - domProps: { - innerHTML: syntaxHighlight(token.node.props.code) + return [createElement(MkCode, { + key: Math.random(), + props: { + code: token.node.props.code, + lang: token.node.props.lang, + inline: true } })]; } diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.vue b/src/client/app/common/views/components/misskey-flavored-markdown.vue index 448df9aa8..5cb102240 100644 --- a/src/client/app/common/views/components/misskey-flavored-markdown.vue +++ b/src/client/app/common/views/components/misskey-flavored-markdown.vue @@ -24,25 +24,10 @@ export default Vue.extend({ background var(--mfmTitleBg) border-radius 4px - >>> .code - margin 8px 0 - >>> .quote margin 8px padding 6px 0 6px 12px color var(--mfmQuote) border-left solid 3px var(--mfmQuoteLine) - >>> code - padding 4px 8px - margin 0 0.5em - font-size 90% - color #525252 - background var(--bg) - border-radius 2px - - >>> pre > code - padding 16px - margin 0 - diff --git a/src/mfm/syntax-highlight.ts b/src/mfm/syntax-highlight.ts deleted file mode 100644 index 109923fb7..000000000 --- a/src/mfm/syntax-highlight.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { capitalize, toUpperCase } from '../prelude/string'; - -function escape(text: string) { - return text - .replace(/>/g, '>') - .replace(/ b.length - a.length); - -const symbols = [ - '=', - '+', - '-', - '*', - '/', - '%', - '~', - '^', - '&', - '|', - '>', - '<', - '!', - '?' -]; - -type Token = { - html: string - next: number -}; - -type Element = (code: string, i: number, source: string) => (Token | null); - -const elements: Element[] = [ - // comment - code => { - if (code.substr(0, 2) != '//') return null; - const match = code.match(/^\/\/(.+?)(\n|$)/); - if (!match) return null; - const comment = match[0]; - return { - html: `${escape(comment)}`, - next: comment.length - }; - }, - - // block comment - code => { - const match = code.match(/^\/\*([\s\S]+?)\*\//); - if (!match) return null; - return { - html: `${escape(match[0])}`, - next: match[0].length - }; - }, - - // string - code => { - if (!/^['"`]/.test(code)) return null; - const begin = code[0]; - let str = begin; - let thisIsNotAString = false; - for (let i = 1; i < code.length; i++) { - const char = code[i]; - if (char == '\\') { - str += char; - str += code[i + 1] || ''; - i++; - continue; - } else if (char == begin) { - str += char; - break; - } else if (char == '\n' || i == (code.length - 1)) { - thisIsNotAString = true; - break; - } else { - str += char; - } - } - if (thisIsNotAString) { - return null; - } else { - return { - html: `${escape(str)}`, - next: str.length - }; - } - }, - - // regexp - code => { - if (code[0] != '/') return null; - let regexp = ''; - let thisIsNotARegexp = false; - for (let i = 1; i < code.length; i++) { - const char = code[i]; - if (char == '\\') { - regexp += char; - regexp += code[i + 1] || ''; - i++; - continue; - } else if (char == '/') { - break; - } else if (char == '\n' || i == (code.length - 1)) { - thisIsNotARegexp = true; - break; - } else { - regexp += char; - } - } - - if (thisIsNotARegexp) return null; - if (regexp == '') return null; - if (regexp.startsWith(' ') && regexp.endsWith(' ')) return null; - - return { - html: `/${escape(regexp)}/`, - next: regexp.length + 2 - }; - }, - - // label - code => { - if (code[0] != '@') return null; - const match = code.match(/^@([a-zA-Z_-]+?)\n/); - if (!match) return null; - const label = match[0]; - return { - html: `${label}`, - next: label.length - }; - }, - - // number - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - if (!/^[\-\+]?[0-9\.]+/.test(code)) return null; - const match = code.match(/^[\-\+]?[0-9\.]+/)[0]; - if (match) { - return { - html: `${match}`, - next: match.length - }; - } else { - return null; - } - }, - - // nan - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - if (code.substr(0, 3) == 'NaN') { - return { - html: `NaN`, - next: 3 - }; - } else { - return null; - } - }, - - // method - code => { - const match = code.match(/^([a-zA-Z_-]+?)\(/); - if (!match) return null; - - if (match[1] == '-') return null; - - return { - html: `${match[1]}`, - next: match[1].length - }; - }, - - // property - (code, i, source) => { - const prev = source[i - 1]; - if (prev != '.') return null; - - const match = code.match(/^[a-zA-Z0-9_-]+/); - if (!match) return null; - - return { - html: `${match[0]}`, - next: match[0].length - }; - }, - - // keyword - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - - const match = keywords.filter(k => code.substr(0, k.length) == k)[0]; - if (match) { - if (/^[a-zA-Z]/.test(code.substr(match.length))) return null; - return { - html: `${match}`, - next: match.length - }; - } else { - return null; - } - }, - - // symbol - code => { - const match = symbols.filter(s => code[0] == s)[0]; - if (match) { - return { - html: `${match}`, - next: 1 - }; - } else { - return null; - } - } -]; - -// TODO: specify lang -export default (source: string, lang?: string): string => { - let code = source; - let html = ''; - - let i = 0; - - function push(token: Token) { - html += token.html; - code = code.substr(token.next); - i += token.next; - } - - while (code != '') { - const parsed = elements.some(el => { - const e = el(code, i, source); - if (e) { - push(e); - return true; - } else { - return false; - } - }); - - if (!parsed) { - push({ - html: escape(code[0]), - next: 1 - }); - } - } - - return html; -}; From b836528b515d80de3253dea1366a8090ebba6c35 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 14:44:39 +0900 Subject: [PATCH 52/56] Celan up --- src/client/app/app.styl | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/src/client/app/app.styl b/src/client/app/app.styl index 13b013328..a98ece7a5 100644 --- a/src/client/app/app.styl +++ b/src/client/app/app.styl @@ -72,47 +72,6 @@ body code font-family Consolas, 'Courier New', Courier, Monaco, monospace - .comment - opacity 0.5 - - .string - color #e96900 - - .regexp - color #e9003f - - .keyword - color #2973b7 - - &.true - &.false - &.null - &.nil - &.undefined - color #ae81ff - - .symbol - color #42b983 - - .number - .nan - color #ae81ff - - .var:not(.keyword) - font-weight bold - font-style italic - //text-decoration underline - - .method - font-style italic - color #8964c1 - - .property - color #a71d5d - - .label - color #e9003f - pre display block From d906d9001052d2cde05b1bd9c2fbfb23a5a66cd2 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 14:55:02 +0900 Subject: [PATCH 53/56] [Server] Introduce admin stream channel --- .../api/endpoints/users/report-abuse.ts | 22 ++++++++++++++++++- src/server/api/stream/channels/admin.ts | 16 ++++++++++++++ src/server/api/stream/channels/index.ts | 2 ++ src/stream.ts | 5 +++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/server/api/stream/channels/admin.ts diff --git a/src/server/api/endpoints/users/report-abuse.ts b/src/server/api/endpoints/users/report-abuse.ts index b520b29e2..19beee433 100644 --- a/src/server/api/endpoints/users/report-abuse.ts +++ b/src/server/api/endpoints/users/report-abuse.ts @@ -2,6 +2,7 @@ import $ from 'cafy'; import ID, { transform } from '../../../../misc/cafy-id'; import define from '../../define'; import User from '../../../../models/user'; import AbuseUserReport from '../../../../models/abuse-user-report'; +import { publishAdminStream } from '../../../../stream'; export const meta = { desc: { @@ -47,12 +48,31 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => { return rej('cannot report admin'); } - await AbuseUserReport.insert({ + const report = await AbuseUserReport.insert({ createdAt: new Date(), userId: user._id, reporterId: me._id, comment: ps.comment }); + // Publish event to moderators + setTimeout(async () => { + const moderators = await User.find({ + $or: [{ + isAdmin: true + }, { + isModerator: true + }] + }); + for (const moderator of moderators) { + publishAdminStream(moderator._id, 'newAbuseUserReport', { + id: report._id, + userId: report.userId, + reporterId: report.reporterId, + comment: report.comment + }); + } + }, 1); + res(); })); diff --git a/src/server/api/stream/channels/admin.ts b/src/server/api/stream/channels/admin.ts new file mode 100644 index 000000000..6bcd1a7e0 --- /dev/null +++ b/src/server/api/stream/channels/admin.ts @@ -0,0 +1,16 @@ +import autobind from 'autobind-decorator'; +import Channel from '../channel'; + +export default class extends Channel { + public readonly chName = 'admin'; + public static shouldShare = true; + public static requireCredential = true; + + @autobind + public async init(params: any) { + // Subscribe admin stream + this.subscriber.on(`adminStream:${this.user._id}`, data => { + this.send(data); + }); + } +} diff --git a/src/server/api/stream/channels/index.ts b/src/server/api/stream/channels/index.ts index 7248579ab..02f71b585 100644 --- a/src/server/api/stream/channels/index.ts +++ b/src/server/api/stream/channels/index.ts @@ -11,6 +11,7 @@ import messagingIndex from './messaging-index'; import drive from './drive'; import hashtag from './hashtag'; import apLog from './ap-log'; +import admin from './admin'; import gamesReversi from './games/reversi'; import gamesReversiGame from './games/reversi-game'; @@ -28,6 +29,7 @@ export default { drive, hashtag, apLog, + admin, gamesReversi, gamesReversiGame }; diff --git a/src/stream.ts b/src/stream.ts index 596cb98e7..098d49ecd 100644 --- a/src/stream.ts +++ b/src/stream.ts @@ -87,6 +87,10 @@ class Publisher { public publishApLogStream = (log: any): void => { this.publish('apLog', null, log); } + + public publishAdminStream = (userId: ID, type: string, value?: any): void => { + this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value); + } } const publisher = new Publisher(); @@ -107,3 +111,4 @@ export const publishHybridTimelineStream = publisher.publishHybridTimelineStream export const publishGlobalTimelineStream = publisher.publishGlobalTimelineStream; export const publishHashtagStream = publisher.publishHashtagStream; export const publishApLogStream = publisher.publishApLogStream; +export const publishAdminStream = publisher.publishAdminStream; From e5d938150386b32d2aa49e1a825453309209d9e4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 16:18:04 +0900 Subject: [PATCH 54/56] [MFM] Add spin syntax Resolve #4003 --- CHANGELOG.md | 1 + src/client/app/animation.styl | 5 +++++ src/client/app/common/views/components/mfm.ts | 11 +++++++++++ src/mfm/html.ts | 6 ++++++ src/mfm/parser.ts | 15 +++++++++++++++ test/mfm.ts | 9 +++++++++ 6 files changed, 47 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9e69e8f0..f8291a135 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ unreleased * 外部サービス認証情報の配信 * 管理画面のモデレーションのUIを強化 * 管理画面からリモートユーザーの情報を更新できるように +* 回転構文の追加 * シンタックスハイライトの強化 * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 diff --git a/src/client/app/animation.styl b/src/client/app/animation.styl index a62916520..9cbd3ec6c 100644 --- a/src/client/app/animation.styl +++ b/src/client/app/animation.styl @@ -26,3 +26,8 @@ transform: translateY(0); } } + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/src/client/app/common/views/components/mfm.ts b/src/client/app/common/views/components/mfm.ts index 8ffa56666..f6f95deb2 100644 --- a/src/client/app/common/views/components/mfm.ts +++ b/src/client/app/common/views/components/mfm.ts @@ -124,6 +124,17 @@ export default Vue.component('misskey-flavored-markdown', { }, genEl(token.children)); } + case 'spin': { + motionCount++; + const isLong = sumTextsLength(token.children) > 5 || countNodesF(token.children) > 3; + const isMany = motionCount > 3; + return (createElement as any)('span', { + attrs: { + style: (this.$store.state.settings.disableAnimatedMfm || isLong || isMany) ? 'display: inline-block;' : 'display: inline-block; animation: spin 1.5s linear infinite;' + }, + }, genEl(token.children)); + } + case 'url': { return [createElement(MkUrl, { key: Math.random(), diff --git a/src/mfm/html.ts b/src/mfm/html.ts index 6af283385..a40ff19ac 100644 --- a/src/mfm/html.ts +++ b/src/mfm/html.ts @@ -55,6 +55,12 @@ export default (tokens: MfmForest, mentionedRemoteUsers: INote['mentionedRemoteU return el; }, + spin(token) { + const el = doc.createElement('i'); + appendChildren(token.children, el); + return el; + }, + blockCode(token) { const pre = doc.createElement('pre'); const inner = doc.createElement('code'); diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts index 560e226af..5cd9fc04c 100644 --- a/src/mfm/parser.ts +++ b/src/mfm/parser.ts @@ -91,6 +91,7 @@ const mfm = P.createLanguage({ root: r => P.alt( r.big, r.small, + r.spin, r.bold, r.strike, r.italic, @@ -122,6 +123,7 @@ const mfm = P.createLanguage({ r.hashtag, r.emoji, r.math, + r.spin, r.text ).atLeast(1).tryParse(x), {})), //#endregion @@ -140,6 +142,15 @@ const mfm = P.createLanguage({ ).atLeast(1).tryParse(x), {})), //#endregion + //#region Spin + spin: r => + P.regexp(/(.+?)<\/spin>/, 1) + .map(x => createTree('spin', P.alt( + r.emoji, + r.text + ).atLeast(1).tryParse(x), {})), + //#endregion + //#region Block code blockCode: r => newline.then( @@ -173,6 +184,7 @@ const mfm = P.createLanguage({ .map(x => createTree('center', P.alt( r.big, r.small, + r.spin, r.bold, r.strike, r.italic, @@ -261,6 +273,7 @@ const mfm = P.createLanguage({ return createTree('link', P.alt( r.big, r.small, + r.spin, r.bold, r.strike, r.italic, @@ -304,6 +317,7 @@ const mfm = P.createLanguage({ .map(x => createTree('motion', P.alt( r.bold, r.small, + r.spin, r.strike, r.italic, r.mention, @@ -364,6 +378,7 @@ const mfm = P.createLanguage({ const contents = P.alt( r.big, r.small, + r.spin, r.bold, r.strike, r.italic, diff --git a/test/mfm.ts b/test/mfm.ts index a5ea4b293..d8cba8ee1 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -244,6 +244,15 @@ describe('MFM', () => { ]); }); + it('spin', () => { + const tokens = analyze(':foo:'); + assert.deepStrictEqual(tokens, [ + tree('spin', [ + leaf('emoji', { name: 'foo' }) + ], {}), + ]); + }); + describe('motion', () => { it('by triple brackets', () => { const tokens = analyze('(((foo)))'); From 4de62220e3f0e2ed759d31b633ef267b12ec16b3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 16:31:00 +0900 Subject: [PATCH 55/56] [MFM] Add flip syntax Resolve #4002 --- CHANGELOG.md | 1 + src/client/app/common/views/components/mfm.ts | 8 +++++++ src/mfm/html.ts | 6 +++++ src/mfm/parser.ts | 24 +++++++++++++++++++ test/mfm.ts | 9 +++++++ 5 files changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8291a135..e9319075c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ unreleased * 管理画面のモデレーションのUIを強化 * 管理画面からリモートユーザーの情報を更新できるように * 回転構文の追加 +* 左右反転構文の追加 * シンタックスハイライトの強化 * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * イタリック構文の判定の改善 diff --git a/src/client/app/common/views/components/mfm.ts b/src/client/app/common/views/components/mfm.ts index f6f95deb2..a3849e960 100644 --- a/src/client/app/common/views/components/mfm.ts +++ b/src/client/app/common/views/components/mfm.ts @@ -135,6 +135,14 @@ export default Vue.component('misskey-flavored-markdown', { }, genEl(token.children)); } + case 'flip': { + return (createElement as any)('span', { + attrs: { + style: 'display: inline-block; transform: scaleX(-1);' + }, + }, genEl(token.children)); + } + case 'url': { return [createElement(MkUrl, { key: Math.random(), diff --git a/src/mfm/html.ts b/src/mfm/html.ts index a40ff19ac..568a39bc7 100644 --- a/src/mfm/html.ts +++ b/src/mfm/html.ts @@ -61,6 +61,12 @@ export default (tokens: MfmForest, mentionedRemoteUsers: INote['mentionedRemoteU return el; }, + flip(token) { + const el = doc.createElement('span'); + appendChildren(token.children, el); + return el; + }, + blockCode(token) { const pre = doc.createElement('pre'); const inner = doc.createElement('code'); diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts index 5cd9fc04c..1cf1edfa4 100644 --- a/src/mfm/parser.ts +++ b/src/mfm/parser.ts @@ -102,6 +102,7 @@ const mfm = P.createLanguage({ r.hashtag, r.emoji, r.blockCode, + r.flip, r.inlineCode, r.quote, r.math, @@ -173,6 +174,7 @@ const mfm = P.createLanguage({ r.hashtag, r.url, r.link, + r.flip, r.emoji, r.text ).atLeast(1).tryParse(x), {})), @@ -195,6 +197,7 @@ const mfm = P.createLanguage({ r.math, r.url, r.link, + r.flip, r.text ).atLeast(1).tryParse(x), {})), //#endregion @@ -228,6 +231,23 @@ const mfm = P.createLanguage({ }), //#endregion + //#region Flip + flip: r => + P.regexp(/(.+?)<\/flip>/, 1) + .map(x => createTree('flip', P.alt( + r.big, + r.small, + r.spin, + r.bold, + r.strike, + r.link, + r.italic, + r.motion, + r.emoji, + r.text + ).atLeast(1).tryParse(x), {})), + //#endregion + //#region Inline code inlineCode: r => P.regexp(/`([^´\n]+?)`/, 1) @@ -253,6 +273,7 @@ const mfm = P.createLanguage({ r.hashtag, r.url, r.link, + r.flip, r.emoji, r.text ).atLeast(1).tryParse(x), {})), @@ -325,6 +346,7 @@ const mfm = P.createLanguage({ r.emoji, r.url, r.link, + r.flip, r.math, r.text ).atLeast(1).tryParse(x), {})), @@ -363,6 +385,7 @@ const mfm = P.createLanguage({ r.hashtag, r.url, r.link, + r.flip, r.emoji, r.text ).atLeast(1).tryParse(x), {})), @@ -385,6 +408,7 @@ const mfm = P.createLanguage({ r.motion, r.url, r.link, + r.flip, r.mention, r.hashtag, r.emoji, diff --git a/test/mfm.ts b/test/mfm.ts index d8cba8ee1..e48bba09e 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -244,6 +244,15 @@ describe('MFM', () => { ]); }); + it('flip', () => { + const tokens = analyze('foo'); + assert.deepStrictEqual(tokens, [ + tree('flip', [ + text('flip') + ], {}), + ]); + }); + it('spin', () => { const tokens = analyze(':foo:'); assert.deepStrictEqual(tokens, [ From 8c62aafa973457bd5abbe43747e69b9655a5761f Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 27 Jan 2019 16:36:01 +0900 Subject: [PATCH 56/56] Fix test --- test/mfm.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mfm.ts b/test/mfm.ts index e48bba09e..2eeaeb2e5 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -248,7 +248,7 @@ describe('MFM', () => { const tokens = analyze('foo'); assert.deepStrictEqual(tokens, [ tree('flip', [ - text('flip') + text('foo') ], {}), ]); });