[MFM] Add spin syntax

Resolve #4003
This commit is contained in:
syuilo 2019-01-27 16:18:04 +09:00
parent d906d90010
commit e5d9381503
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
6 changed files with 47 additions and 0 deletions

View file

@ -7,6 +7,7 @@ unreleased
* 外部サービス認証情報の配信 * 外部サービス認証情報の配信
* 管理画面のモデレーションのUIを強化 * 管理画面のモデレーションのUIを強化
* 管理画面からリモートユーザーの情報を更新できるように * 管理画面からリモートユーザーの情報を更新できるように
* 回転構文の追加
* シンタックスハイライトの強化 * シンタックスハイライトの強化
* 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正 * 引用投稿を削除したとき単なるRenoteとしてタイムラインに残る問題を修正
* イタリック構文の判定の改善 * イタリック構文の判定の改善

View file

@ -26,3 +26,8 @@
transform: translateY(0); transform: translateY(0);
} }
} }
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

View file

@ -124,6 +124,17 @@ export default Vue.component('misskey-flavored-markdown', {
}, genEl(token.children)); }, genEl(token.children));
} }
case 'spin': {
motionCount++;
const isLong = sumTextsLength(token.children) > 5 || countNodesF(token.children) > 3;
const isMany = motionCount > 3;
return (createElement as any)('span', {
attrs: {
style: (this.$store.state.settings.disableAnimatedMfm || isLong || isMany) ? 'display: inline-block;' : 'display: inline-block; animation: spin 1.5s linear infinite;'
},
}, genEl(token.children));
}
case 'url': { case 'url': {
return [createElement(MkUrl, { return [createElement(MkUrl, {
key: Math.random(), key: Math.random(),

View file

@ -55,6 +55,12 @@ export default (tokens: MfmForest, mentionedRemoteUsers: INote['mentionedRemoteU
return el; return el;
}, },
spin(token) {
const el = doc.createElement('i');
appendChildren(token.children, el);
return el;
},
blockCode(token) { blockCode(token) {
const pre = doc.createElement('pre'); const pre = doc.createElement('pre');
const inner = doc.createElement('code'); const inner = doc.createElement('code');

View file

@ -91,6 +91,7 @@ const mfm = P.createLanguage({
root: r => P.alt( root: r => P.alt(
r.big, r.big,
r.small, r.small,
r.spin,
r.bold, r.bold,
r.strike, r.strike,
r.italic, r.italic,
@ -122,6 +123,7 @@ const mfm = P.createLanguage({
r.hashtag, r.hashtag,
r.emoji, r.emoji,
r.math, r.math,
r.spin,
r.text r.text
).atLeast(1).tryParse(x), {})), ).atLeast(1).tryParse(x), {})),
//#endregion //#endregion
@ -140,6 +142,15 @@ const mfm = P.createLanguage({
).atLeast(1).tryParse(x), {})), ).atLeast(1).tryParse(x), {})),
//#endregion //#endregion
//#region Spin
spin: r =>
P.regexp(/<spin>(.+?)<\/spin>/, 1)
.map(x => createTree('spin', P.alt(
r.emoji,
r.text
).atLeast(1).tryParse(x), {})),
//#endregion
//#region Block code //#region Block code
blockCode: r => blockCode: r =>
newline.then( newline.then(
@ -173,6 +184,7 @@ const mfm = P.createLanguage({
.map(x => createTree('center', P.alt( .map(x => createTree('center', P.alt(
r.big, r.big,
r.small, r.small,
r.spin,
r.bold, r.bold,
r.strike, r.strike,
r.italic, r.italic,
@ -261,6 +273,7 @@ const mfm = P.createLanguage({
return createTree('link', P.alt( return createTree('link', P.alt(
r.big, r.big,
r.small, r.small,
r.spin,
r.bold, r.bold,
r.strike, r.strike,
r.italic, r.italic,
@ -304,6 +317,7 @@ const mfm = P.createLanguage({
.map(x => createTree('motion', P.alt( .map(x => createTree('motion', P.alt(
r.bold, r.bold,
r.small, r.small,
r.spin,
r.strike, r.strike,
r.italic, r.italic,
r.mention, r.mention,
@ -364,6 +378,7 @@ const mfm = P.createLanguage({
const contents = P.alt( const contents = P.alt(
r.big, r.big,
r.small, r.small,
r.spin,
r.bold, r.bold,
r.strike, r.strike,
r.italic, r.italic,

View file

@ -244,6 +244,15 @@ describe('MFM', () => {
]); ]);
}); });
it('spin', () => {
const tokens = analyze('<spin>:foo:</spin>');
assert.deepStrictEqual(tokens, [
tree('spin', [
leaf('emoji', { name: 'foo' })
], {}),
]);
});
describe('motion', () => { describe('motion', () => {
it('by triple brackets', () => { it('by triple brackets', () => {
const tokens = analyze('(((foo)))'); const tokens = analyze('(((foo)))');