Skip to content

Commit

Permalink
ルビ (#4743)
Browse files Browse the repository at this point in the history
* ruby

* a

* fix

* autocomplete

* multi

* format

* tree
  • Loading branch information
mei23 committed Nov 17, 2023
1 parent 8fd5246 commit b21b4b3
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/client/app/common/views/components/autocomplete.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ const fnDb: MfmDef[] = [
{ name: 'font.serif', head: '$[font.serif ', tail: ']', desc: '$[font.serif serif]' },
{ name: 'font.monospace', head: '$[font.monospace ', tail: ']', desc: '$[font.monospace monospace]' },
{ name: 'ruby', head: '$[ruby ', tail: ']', desc: '$[ruby 文字 ルビ]' },
];
export default Vue.extend({
Expand Down
6 changes: 6 additions & 0 deletions src/client/app/common/views/components/mfm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,12 @@ export default Vue.component('misskey-flavored-markdown', {
}
}, genEl(node.children, fixedSize))];
}
case 'ruby': {
return [createElement('ruby', [
genEl(node.children, true),
createElement('rt', node.props.args.rt)
])];
}
}

return (createElement as any)('span', {
Expand Down
7 changes: 7 additions & 0 deletions src/client/app/common/views/pages/mfm-cheat-sheet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@
<ui-textarea :slim="false" class="text" v-model="preview_italic"></ui-textarea>
</section>

<section>
<header>ルビ</header>
<p><mfm :text="preview_ruby" :key="preview_ruby"/></p>
<ui-textarea :slim="true" class="text" v-model="preview_ruby"></ui-textarea>
</section>

<section>
<header>上付き・下付き</header>
<p><mfm :text="preview_supsub" :key="preview_supsub"/></p>
Expand Down Expand Up @@ -281,6 +287,7 @@ export default Vue.extend({
preview_italic: '<i>これは斜体</i>\n_a先頭がアルファベットとかと接着してれば斜体になる構文_\n*a先頭がアルファベットとかと接着してれば斜体になる構文*',
preview_strike: '~~環境によって意味が変わるとかめんどくさいこと言われる打ち消し線です~~',
preview_color: '<color #0000ff lightpink>前景色と背景色</color>',
preview_ruby: '$[ruby 魑魅魍魎 ちみもうりょう]',
preview_supsub: '上付き<sup>a</sup>\n下付き<sub>b</sub>',
preview_quote: `> これは引用です`,
preview_center: `<center>中央に</center>`,
Expand Down
24 changes: 24 additions & 0 deletions src/mfm/from-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as parse5 from 'parse5';
import treeAdapter = require('parse5/lib/tree-adapters/default');
import { URL } from 'url';
import { urlRegexFull } from './utils';
import { inspect } from 'util';

export function fromHtml(html: string, hashtagNames?: string[]): string | null {
if (html == null) return null;
Expand Down Expand Up @@ -201,6 +202,29 @@ export function fromHtml(html: string, hashtagNames?: string[]): string | null {
break;
}

case 'ruby':
{
const ts = [];
let rt = '';

for (const n of node.childNodes) {
if (treeAdapter.isTextNode(n)) {
ts.push(n.value);
} else if (treeAdapter.isElementNode(n)) {
if (n.nodeName === 'rt') {
rt += getText(n);
} else if (n.nodeName === 'rp') {
continue;
} else {
ts.push(getText(n));
}
}
}

text += `$[ruby ${ts.join('')} ${rt}]`;
break;
}

default:
appendChildren(node.childNodes);
break;
Expand Down
9 changes: 8 additions & 1 deletion src/mfm/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,18 @@ export const mfmLanguage = P.createLanguage({
const argsPart = match[2];
const content = match[3];

if (!['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'rgbshift', 'x1', 'x2', 'x3', 'x4', 'font', 'blur'].includes(name)) {
if (!['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'rgbshift', 'x1', 'x2', 'x3', 'x4', 'font', 'blur', 'ruby'].includes(name)) {
return P.makeFailure(i, 'unknown fn name');
}

const args: Record<string, boolean | string> = {};

if (['ruby'].includes(name)) {
const splited = content.split(/ +/);
args.rt = splited[1] ?? '';
return P.makeSuccess(i + match[0].length, { name, args, content: splited[0] });
}

for (const arg of argsPart?.split(',') || []) {
const kv = arg.split('=');
if (kv[0] == '__proto__') return P.makeFailure(i, 'prototype pollution');
Expand Down
26 changes: 26 additions & 0 deletions src/mfm/to-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,32 @@ export function toHtml(nodes: MfmNode[] | null, mentionedRemoteUsers: INote['men
return el;
}

if (node.type === 'fn') {
if (node.props.name === 'ruby') {
const ruby = doc.createElement('ruby');

if (node.children.length === 1 && node.children[0].type === 'text') {
ruby.textContent = node.children[0].props.text;
} else {
appendChildren(node.children, ruby);
}

const rp1 = doc.createElement('rp');
rp1.textContent = '(';
ruby.appendChild(rp1);

const rt = doc.createElement('rt');
rt.textContent = node.props.args.rt;
ruby.appendChild(rt);

const rp2 = doc.createElement('rp');
rp2.textContent = ')';
ruby.appendChild(rp2);

return ruby;
}
}

/*
if (['sub', 'sup'].includes(node.type)) {
const el = doc.createElement(node.type);
Expand Down
13 changes: 13 additions & 0 deletions test/mfm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,14 @@ describe('fromHtml', () => {
it('title', () => {
assert.deepStrictEqual(fromHtml('<p>a<h1>b</h1>c</p>'), 'a【b】\nc');
});

it('ruby', () => {
assert.deepStrictEqual(fromHtml('<p><ruby>魑魅魍魎<rp>(</rp><rt>ちみもうりょう</rt><rp>)</rp></ruby></p>'), '$[ruby 魑魅魍魎 ちみもうりょう]');
});

it('ruby - multi', () => {
assert.deepStrictEqual(fromHtml('<p><ruby><rb>魑魅魍魎</rb>百鬼夜行<rp>(</rp><rt>ちみもうりょう</rt><rt>ひゃっきやこう</rt><rp>)</rp></ruby></p>'), '$[ruby 魑魅魍魎百鬼夜行 ちみもうりょうひゃっきやこう]');
});
});

describe('toHtml', () => {
Expand Down Expand Up @@ -1472,6 +1480,11 @@ describe('toHtml', () => {
assert.equal(toHtml(parseFull('【a】')!), `<p><h1><span>a</span></h1></p>`);
});

it('ruby', () => {
assert.equal(toHtml(parseFull('$[ruby 魑魅魍魎 ちみもうりょう]')!), `<p><ruby>魑魅魍魎<rp>(</rp><rt>ちみもうりょう</rt><rp>)</rp></ruby></p>`);
});


/*
it('fn', () => {
assert.equal(toHtml(parseFull('$[spin.y,left,speed=1s,delay=0.3s a]')!), `<p><i data-mfm="spin" data-mfm-y="1" data-mfm-left="1" data-mfm-speed="1s" data-mfm-delay="0.3s"><span>a</span></i></p>`);
Expand Down

0 comments on commit b21b4b3

Please sign in to comment.