From dc77c104936aa15d504fbfd74658d57d7c5f5ce7 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 18:38:58 +0900 Subject: [PATCH 1/6] =?UTF-8?q?(enhance)=20MFM=20ruby=E3=81=8C=E9=80=A3?= =?UTF-8?q?=E5=90=88=E3=81=95=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/MfmService.ts | 73 +++++++++++++++++++++---- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index af602168d4ac..88030cb1573b 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -276,17 +276,68 @@ export class MfmService { }, fn: (node) => { - if (node.props.name === 'unixtime') { - const text = node.children[0]!.type === 'text' ? node.children[0].props.text : ''; - const date = new Date(parseInt(text, 10) * 1000); - const el = doc.createElement('time'); - el.setAttribute('datetime', date.toISOString()); - el.textContent = date.toISOString(); - return el; - } else { - const el = doc.createElement('i'); - appendChildren(node.children, el); - return el; + switch (node.props.name) { + case 'unixtime': { + const text = node.children[0]!.type === 'text' ? node.children[0].props.text : ''; + const date = new Date(parseInt(text, 10) * 1000); + const el = doc.createElement('time'); + el.setAttribute('datetime', date.toISOString()); + el.textContent = date.toISOString(); + return el; + } + + case 'ruby': { + if (node.children.length === 1) { + const child = node.children[0]; + const text = child.type === 'text' ? child.props.text : ''; + const rubyEl = doc.createElement('ruby'); + const rtEl = doc.createElement('rt'); + + // ruby未対応のHTMLサニタイザーを通したときにルビが「劉備(りゅうび)」となるようにする + const rpStartEl = doc.createElement('rp'); + rpStartEl.appendChild(doc.createTextNode('(')); + const rpEndEl = doc.createElement('rp'); + rpEndEl.appendChild(doc.createTextNode(')')); + + rubyEl.appendChild(doc.createTextNode(text.split(' ')[0])); + rtEl.appendChild(doc.createTextNode(text.split(' ')[1])); + rubyEl.appendChild(rpStartEl); + rubyEl.appendChild(rtEl); + rubyEl.appendChild(rpEndEl); + return rubyEl; + } else { + const rt = node.children.at(-1); + + if (!rt) { + const el = doc.createElement('i'); + appendChildren(node.children, el); + return el; + } + + const text = rt.type === 'text' ? rt.props.text : ''; + const rubyEl = doc.createElement('ruby'); + const rtEl = doc.createElement('rt'); + + // ruby未対応のHTMLサニタイザーを通したときにルビが「劉備(りゅうび)」となるようにする + const rpStartEl = doc.createElement('rp'); + rpStartEl.appendChild(doc.createTextNode('(')); + const rpEndEl = doc.createElement('rp'); + rpEndEl.appendChild(doc.createTextNode(')')); + + appendChildren(node.children.slice(0, node.children.length - 1), rubyEl); + rtEl.appendChild(doc.createTextNode(text.trim())); + rubyEl.appendChild(rpStartEl); + rubyEl.appendChild(rtEl); + rubyEl.appendChild(rpEndEl); + return rubyEl; + } + } + + default: { + const el = doc.createElement('i'); + appendChildren(node.children, el); + return el; + } } }, From f74bb89f31235f44aa212738ff6451f17720e7ef Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 18:39:32 +0900 Subject: [PATCH 2/6] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc39e423c031..b87f7848339f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367 ### Server +- Enhance: MFM `$[ruby ]` が連合されるように - Fix: 時間経過により無効化されたアンテナを再有効化したとき、サーバ再起動までその状況が反映されないのを修正 #12303 - Fix: ロールタイムラインが保存されない問題を修正 - Fix: api.jsonの生成ロジックを改善 #12402 From 7e3ed291e6fdee4b61be3d6cf6712f08efd88a0b Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 18:43:14 +0900 Subject: [PATCH 3/6] Update Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b87f7848339f..eed472cc2c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ - Fix: ウィジェットのジョブキューにて音声の発音方法変更に追従できていなかったのを修正 #12367 ### Server -- Enhance: MFM `$[ruby ]` が連合されるように +- Enhance: MFM `$[ruby ]` が他ソフトウェアと連合されるように - Fix: 時間経過により無効化されたアンテナを再有効化したとき、サーバ再起動までその状況が反映されないのを修正 #12303 - Fix: ロールタイムラインが保存されない問題を修正 - Fix: api.jsonの生成ロジックを改善 #12402 From a9e28d8252c2b82a9cb6bb3f4a77081e7d70d42b Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 18:57:00 +0900 Subject: [PATCH 4/6] =?UTF-8?q?(fix)=20unixtime=E3=81=AE=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=83=90=E3=83=83=E3=82=AF=20(AP)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/MfmService.ts | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 88030cb1573b..e74c62e1a81c 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -250,6 +250,12 @@ export class MfmService { } } + function fnDefault(node: mfm.MfmFn) { + const el = doc.createElement('i'); + appendChildren(node.children, el); + return el; + } + const handlers: { [K in mfm.MfmNode['type']]: (node: mfm.NodeType) => any } = { bold: (node) => { const el = doc.createElement('b'); @@ -278,12 +284,16 @@ export class MfmService { fn: (node) => { switch (node.props.name) { case 'unixtime': { - const text = node.children[0]!.type === 'text' ? node.children[0].props.text : ''; - const date = new Date(parseInt(text, 10) * 1000); - const el = doc.createElement('time'); - el.setAttribute('datetime', date.toISOString()); - el.textContent = date.toISOString(); - return el; + const text = node.children[0].type === 'text' ? node.children[0].props.text : ''; + try { + const date = new Date(parseInt(text, 10) * 1000); + const el = doc.createElement('time'); + el.setAttribute('datetime', date.toISOString()); + el.textContent = date.toISOString(); + return el; + } catch (err) { + return fnDefault(node); + } } case 'ruby': { @@ -309,9 +319,7 @@ export class MfmService { const rt = node.children.at(-1); if (!rt) { - const el = doc.createElement('i'); - appendChildren(node.children, el); - return el; + return fnDefault(node); } const text = rt.type === 'text' ? rt.props.text : ''; @@ -334,9 +342,7 @@ export class MfmService { } default: { - const el = doc.createElement('i'); - appendChildren(node.children, el); - return el; + return fnDefault(node); } } }, From 553697b27315aafa896c49dec7181e8a61145488 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 19:08:59 +0900 Subject: [PATCH 5/6] =?UTF-8?q?(fix)=20unixtime=E3=81=AE=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=83=AB=E3=83=90=E3=83=83=E3=82=AF=20(frontend)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 2 +- .../frontend/src/components/global/MkTime.vue | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 3757715c0ff0..c10faa382825 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1855,7 +1855,7 @@ _ago: weeksAgo: "{n}週間前" monthsAgo: "{n}ヶ月前" yearsAgo: "{n}年前" - invalid: "ありません" + invalid: "日時の解析に失敗" _timeIn: seconds: "{n}秒後" diff --git a/packages/frontend/src/components/global/MkTime.vue b/packages/frontend/src/components/global/MkTime.vue index f08d538fc0ed..2eeab4d28455 100644 --- a/packages/frontend/src/components/global/MkTime.vue +++ b/packages/frontend/src/components/global/MkTime.vue @@ -28,12 +28,25 @@ const props = withDefaults(defineProps<{ mode: 'relative', }); -const _time = props.time == null ? NaN : - typeof props.time === 'number' ? props.time : - (props.time instanceof Date ? props.time : new Date(props.time)).getTime(); +function getDateSafe(n: Date | string | number) { + try { + if (n instanceof Date) { + return n; + } + return new Date(n); + } catch (err) { + return { + getTime: () => NaN, + }; + } +} + +// eslint-disable-next-line vue/no-setup-props-destructure +const _time = props.time == null ? NaN : getDateSafe(props.time).getTime(); const invalid = Number.isNaN(_time); const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid; +// eslint-disable-next-line vue/no-setup-props-destructure let now = $ref((props.origin ?? new Date()).getTime()); const ago = $computed(() => (now - _time) / 1000/*ms*/); From 8f5263a2081a92f9bafb26c0686eb812ebab75b4 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih Date: Thu, 23 Nov 2023 19:11:23 +0900 Subject: [PATCH 6/6] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eed472cc2c0e..fbe3e56d2799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### General - Feat: メールアドレスの認証にverifymail.ioを使えるように (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/971ba07a44550f68d2ba31c62066db2d43a0caed) - Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83) +- Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正 ### Client - Enhance: 絵文字のオートコンプリート機能強化 #12364