From e7bfcecf7be15965b649a7a52554271f3b88ac69 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 7499c6b80fb19fb0e007a42d9484439a2410924a 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 ef2ff22cd928f707ca8cc2dad0437130714079d1 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 8c9fe1093ea0cd8cffc9c6246e7d39b5dfb2fadc 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 1588567410e32a3ec53a3d54fbf1bd61d2fd9f8b 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 d729453d7c72b268ccb4d112edb269a115f3dd73 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 4ab9b5bb8e7b06be41f7d8f0e8ceb9304558fcdd 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 069e786131fc54e39465fcab168708c8bf2f06ff 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 ff3412596f9efb2250ffad6811e62bdfebe8a905 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 df9bc71348d33d45e73495ffc341c51f97840408 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 9d058f43e4f416d7e9f99e8ab8272cf9cb9ab2f4 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 10f7ef85fbf2238908f412ad5f13de5977dacfec 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 20a9f8dcbd4ef267aad642a87de64e1ac5945eec 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 68bf191761337c92219a4141d919318dacf845e8 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 c07005f29b63ebaf3ac9d781266f31d80566a357 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 2a10adc35521d1baee9c598711d3e3c76533a812 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 6b4e0fb386c20609f592254e586889b161a8cefa 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 6889ada3af4d0c10fc29419421f62e28758efa56 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 a41e67ea09fd84d8ce1085fce9e643f83a830e8f 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 50858384af4648338dae1ddbdae2f9894e50d231 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 f3e8d0ab4cf2e659eef5e9faec7a11350785c525 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 f4ea254a30643d7d3d45a63adfc022035a2e1036 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 22f84f88a349fd3b037d3ac6690c02c4687ef5d8 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 2258d1f7939061b62c53f009baae8996a8ff8c67 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 3734e8e3bbe48e968c6f9555a69748f86a46bd6e 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 485fb75eb2abed231f6d124d06ab64f05f312918 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 2b439101711ebae3f8f5dd6a78f04c63acb143cf 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 9d5ca9305a3d1af945917ded9d61250357c5a6f9 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 501da8fbffdedfc88aee16b388354ce4e3c8cb1b 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 0031530857f160fa6bfcf3ac3ffe38fad1466442 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 c5d81776f805f7fad33971ff455926ea87161edd 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 ec385c1fee62a25cdeddf8baedf1bce1dbcb65c1 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 03bba8d3ebe680bab7e74addcbc2556883656ba0 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 49fe75e4b4acb1f67fa1dd6f3b2dd1d6ee93d9c1 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 239909abec7a6840088305db8af3ec293a9ce462 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 366068c456d7d09b1511954fdfc99e6366383498 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 798d312d2b28d35d4e398d11549ea5a2aa1ddcfb 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 39400dd9b675d2b3f34341b6ebd93e209326a1df 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 506827f41e0848b55eb35a3247a8613b981af3e2 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 b9e98ec542ad7cb75d2db1b19b4d164b64bf69e3 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 b7160f160bb859ca6022f3577c314c7861b1e935 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 f6a90080c6aad527d9fb033af3e57d576d101e1d 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 8955e40e5acc33f92f590aa9838a70431de503ee 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 8ef671f40c468701bc7ec4b317b0e635f2ac79a5 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 1fa85492e358837b34f0dc7820bbaa488b3aedfa 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 4f810bab1a289a1aa3fc9cb71d78b7c4b94c8fa5 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 b5f0911146ec6147dc9b4b4810381eabdc434e16 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 febd83e7ace8db4a2433ca2041d120d0a6d80d6e 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 eae0ff45c6e3bf3557551a84b4cd39b15f7362c6 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 4d443344c9d7f222c4c9ea2b2b6ca9aba051c96b 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 daa19636458b497a0ac50556f19285026f344c96 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 c08a217a9c72e9464ca38fca092081b98c18ef0c 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 d5439d467756df6b1a3b504248b11c185acd3acb 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 5f10be3f9a901e74f68dc1d42659f43ada0c6437 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 ee81bd29553c2bb49bc9103f41360578422caad9 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 c5fef1cc32a3eab5c2cddf37f3267457eb21adf4 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') ], {}), ]); });