summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHong Minhee (洪 民憙) <hong@minhee.org>2025-01-14 22:06:39 +0900
committerGitHub <noreply@github.com>2025-01-14 13:06:39 +0000
commitd018fe58aa91eb702b098df659f23f9a981f4368 (patch)
tree8779dd2e0fb45cb7762a7d3c9a5f562487b1e564
parentenhance(backend): 絵文字の連合でライセンス欄を相互にやり... (diff)
downloadsharkey-d018fe58aa91eb702b098df659f23f9a981f4368.tar.gz
sharkey-d018fe58aa91eb702b098df659f23f9a981f4368.tar.bz2
sharkey-d018fe58aa91eb702b098df659f23f9a981f4368.zip
fix(backend): Let MfmService.fromHtml accept ruby (#15117)
This fix makes `MfmService.fromHtml()` method accept `<ruby>` tags and translate it to MFM's ruby characters syntax (`$[ruby ...]`). このパッチは`MfmService.fromHtml()`メソッドが`<ruby>`タグをMFMの 読み仮名(ルビ)文法に翻訳する様に修正します。
-rw-r--r--CHANGELOG.md1
-rw-r--r--packages/backend/src/core/MfmService.ts33
-rw-r--r--packages/backend/test/unit/MfmService.ts18
3 files changed, 52 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eddcd86b0b..9380f23cfb 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`<ruby>`タグを含むノートを受信した場合、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 8061622340..bf06d4457e 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 (<pre><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 fd4a03413b..36af8823f6 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('<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', () => {
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');
});