handle more complex ruby from/to html - fixes #605

this is not exactly great, but it should be "good enough"

note that the new `group` function should not escape in the wild, as
we don't document it and only use it internally

I tried using `$[scale foo bar]` instead of `$[group foo bar]`, but
that would be rendered as `<i>foo bar</i>` when sent over the network
to non-misskey instances, and we don't want that
This commit is contained in:
dakkar 2025-01-18 12:51:38 +00:00
parent 42d8279610
commit 01a5300be8
3 changed files with 84 additions and 0 deletions

View file

@ -230,6 +230,67 @@ export class MfmService {
break;
}
case 'rp': break
case 'rt': {
appendChildren(node.childNodes);
break;
}
case 'ruby': {
if (node.childNodes) {
/*
we get:
```
<ruby>
some text <rp>(</rp> <rt>annotation</rt> <rp>)</rp>
more text <rt>more annotation<rt>
</ruby>
```
and we want to produce:
```
$[ruby $[group some text] annotation]
$[ruby $[group more text] more annotation]
```
that `group` is a hack, because when the `ruby` render
sees just text inside the `$[ruby]`, it splits on
whitespace, considers the first "word" to be the main
content, and the rest the annotation
with that `group`, we force it to consider the whole
group as the main content
(note that the `rp` are to be ignored, they only exist
for browsers who don't understand ruby)
*/
let nonRtNodes=[];
// scan children, ignore `rp`, split on `rt`
for (const child of node.childNodes) {
if (treeAdapter.isTextNode(child)) {
nonRtNodes.push(child);
continue;
}
if (!treeAdapter.isElementNode(child)) {
continue;
}
if (child.nodeName == 'rp') {
continue;
}
if (child.nodeName == 'rt') {
text += '$[ruby $[group ';
appendChildren(nonRtNodes);
text += '] ';
analyze(child);
text += '] ';
nonRtNodes=[];
continue;
}
nonRtNodes.push(child);
}
}
break;
}
default: // includes inline elements
{
appendChildren(node.childNodes);
@ -348,6 +409,12 @@ export class MfmService {
}
}
case 'group': { // this is mostly a hack for `ruby`
const el = doc.createElement('span');
appendChildren(node.children, el);
return el;
}
default: {
return fnDefault(node);
}