fix(backend): Let MfmService.fromHtml accept ruby

This fix makes `MfmService.fromHtml()` method accept `<ruby>` tags
and translate it to MFM's ruby characters syntax (`$[ruby ...]`).

このパッチは`MfmService.fromHtml()`メソッドが`<ruby>`タグをMFMの
読み仮名(ルビ)文法に翻訳する様に修正します。
This commit is contained in:
Hong Minhee 2024-12-10 18:28:31 +09:00
parent e8bf6285cb
commit a74cc1401d
No known key found for this signature in database
GPG key ID: C429ECD57EED6CCA
3 changed files with 52 additions and 0 deletions

View file

@ -14,6 +14,7 @@
- Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 ) - Fix: ユーザーのプロフィール画面をアドレス入力などで直接表示した際に概要タブの描画に失敗する問題の修正( #15032 )
- Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正 - Fix: 起動前の疎通チェックが機能しなくなっていた問題を修正
(Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737) (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/737)
- Fix: 非Misskey系のソフトウェアからHTML`<ruby>`タグを含むートを受信した場合、MFMの読み仮名ルビ文法に変換して表示
## 2024.11.0 ## 2024.11.0

View file

@ -171,6 +171,39 @@ export class MfmService {
break; 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 (<pre><code>) // block code (<pre><code>)
case 'pre': { case 'pre': {
if (node.childNodes.length === 1 && node.childNodes[0].nodeName === 'code') { if (node.childNodes.length === 1 && node.childNodes[0].nodeName === 'code') {

View file

@ -108,6 +108,24 @@ describe('MfmService', () => {
assert.deepStrictEqual(mfmService.fromHtml('<p>a <a></a> d</p>'), 'a d'); assert.deepStrictEqual(mfmService.fromHtml('<p>a <a></a> d</p>'), 'a d');
}); });
test('ruby', () => {
assert.deepStrictEqual(mfmService.fromHtml('<p>a <ruby>Misskey<rp>(</rp><rt>ミスキー</rt><rp>)</rp></ruby> b</p>'), 'a $[ruby Misskey ミスキー] b');
assert.deepStrictEqual(mfmService.fromHtml('<p>a <ruby>Misskey<rp>(</rp><rt>ミスキー</rt><rp>)</rp>Misskey<rp>(</rp><rt>ミスキー</rt><rp>)</rp></ruby> b</p>'), 'a $[ruby Misskey ミスキー]$[ruby Misskey ミスキー] b');
});
test('ruby with spaces', () => {
assert.deepStrictEqual(mfmService.fromHtml('<p>a <ruby>Miss key<rp>(</rp><rt>ミスキー</rt><rp>)</rp> b</ruby> c</p>'), 'a Miss key(ミスキー) b c');
assert.deepStrictEqual(mfmService.fromHtml('<p>a <ruby>Misskey<rp>(</rp><rt>ミス キー</rt><rp>)</rp> b</ruby> c</p>'), 'a Misskey(ミス キー) b c');
assert.deepStrictEqual(
mfmService.fromHtml('<p>a <ruby>Misskey<rp>(</rp><rt>ミスキー</rt><rp>)</rp>Misskey<rp>(</rp><rt>ミス キー</rt><rp>)</rp>Misskey<rp>(</rp><rt>ミスキー</rt><rp>)</rp></ruby> b</p>'),
'a Misskey(ミスキー)Misskey(ミス キー)Misskey(ミスキー) b'
);
});
test('ruby with other inline tags', () => {
assert.deepStrictEqual(mfmService.fromHtml('<p>a <ruby><strong>Misskey</strong><rp>(</rp><rt>ミスキー</rt><rp>)</rp> b</ruby> c</p>'), 'a **Misskey**(ミスキー) b c');
});
test('mention', () => { test('mention', () => {
assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/@user" class="u-url mention">@user</a> d</p>'), 'a @user@example.com d'); assert.deepStrictEqual(mfmService.fromHtml('<p>a <a href="https://example.com/@user" class="u-url mention">@user</a> d</p>'), 'a @user@example.com d');
}); });