diff --git a/CHANGELOG.md b/CHANGELOG.md index eddcd86b0bab..9380f23cfb9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/869) - Fix: `/api/pages/update`にて`name`を指定せずにリクエストするとエラーが発生する問題を修正 - Fix: AIセンシティブ判定が arm64 環境で動作しない問題を修正 +- Fix: 非Misskey系のソフトウェアからHTML``タグを含むノートを受信した場合、MFMの読み仮名(ルビ)文法に変換して表示 ### Misskey.js - Feat: allow setting `binaryType` of WebSocket connection diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 8061622340b6..bf06d4457e2a 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -171,6 +171,39 @@ export class MfmService { break; } + case 'ruby': { + let ruby: [string, string][] = []; + for (const child of node.childNodes) { + if (child.nodeName === 'rp') { + continue; + } + if (treeAdapter.isTextNode(child) && !/\s|\[|\]/.test(child.value)) { + ruby.push([child.value, '']); + continue; + } + if (child.nodeName === 'rt' && ruby.length > 0) { + const rt = getText(child); + if (/\s|\[|\]/.test(rt)) { + // If any space is included in rt, it is treated as a normal text + ruby = []; + appendChildren(node.childNodes); + break; + } else { + ruby.at(-1)![1] = rt; + continue; + } + } + // If any other element is included in ruby, it is treated as a normal text + ruby = []; + appendChildren(node.childNodes); + break; + } + for (const [base, rt] of ruby) { + text += `$[ruby ${base} ${rt}]`; + } + break; + } + // block code (
)
 				case 'pre': {
 					if (node.childNodes.length === 1 && node.childNodes[0].nodeName === 'code') {
diff --git a/packages/backend/test/unit/MfmService.ts b/packages/backend/test/unit/MfmService.ts
index fd4a03413bb1..36af8823f6fc 100644
--- a/packages/backend/test/unit/MfmService.ts
+++ b/packages/backend/test/unit/MfmService.ts
@@ -108,6 +108,24 @@ describe('MfmService', () => {
 			assert.deepStrictEqual(mfmService.fromHtml('

a d

'), 'a d'); }); + test('ruby', () => { + assert.deepStrictEqual(mfmService.fromHtml('

a Misskey(ミスキー) b

'), 'a $[ruby Misskey ミスキー] b'); + assert.deepStrictEqual(mfmService.fromHtml('

a Misskey(ミスキー)Misskey(ミスキー) b

'), 'a $[ruby Misskey ミスキー]$[ruby Misskey ミスキー] b'); + }); + + test('ruby with spaces', () => { + assert.deepStrictEqual(mfmService.fromHtml('

a Miss key(ミスキー) b c

'), 'a Miss key(ミスキー) b c'); + assert.deepStrictEqual(mfmService.fromHtml('

a Misskey(ミス キー) b c

'), 'a Misskey(ミス キー) b c'); + assert.deepStrictEqual( + mfmService.fromHtml('

a Misskey(ミスキー)Misskey(ミス キー)Misskey(ミスキー) b

'), + 'a Misskey(ミスキー)Misskey(ミス キー)Misskey(ミスキー) b' + ); + }); + + test('ruby with other inline tags', () => { + assert.deepStrictEqual(mfmService.fromHtml('

a Misskey(ミスキー) b c

'), 'a **Misskey**(ミスキー) b c'); + }); + test('mention', () => { assert.deepStrictEqual(mfmService.fromHtml('

a @user d

'), 'a @user@example.com d'); });