summaryrefslogtreecommitdiff
path: root/src/client/components/mfm.ts
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2020-10-17 20:12:00 +0900
committerGitHub <noreply@github.com>2020-10-17 20:12:00 +0900
commit7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a (patch)
tree2263a06acec7fa21882366bae26d1a983ce21135 /src/client/components/mfm.ts
parentCW の input でも投稿ショートカットが動作するように (#6690) (diff)
downloadmisskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.tar.gz
misskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.tar.bz2
misskey-7199e6f4e0b3a2c2bc198e689c3e0cd0d0f0354a.zip
Migrate to Vue3 (#6587)
* Update reaction.vue * fix bug * wip * wip * wjio * wip * Revert "wip" This reverts commit e427f2160adf4e8a4147006e25a89854edab0033. * wip * wip * wip * Update init.ts * Update drive-window.vue * wip * wip * Use PascalCase for components * Use PascalCase for components * update dep * wip * wip * wip * Update init.ts * wip * Update paging.ts * Update test.vue * watch deep * wip * lint * wip * wip * wip * wip * wiop * wip * Update webpack.config.ts * alllow null poll * wip * wip * wip * wiop * UI redesign & refactor (#6714) * wip * wip * wip * wip * wip * Update drive.vue * Update word-mute.vue * wip * wip * wip * clean up * wip * Update default.vue * wip * Update notes.vue * Update mfm.ts * Update index.home.vue * Update post-form.vue * Update post-form-attaches.vue * wip * Update post-form.vue * Update sidebar.vue * wip * wip * Update index.vue * wip * Update default.vue * Update index.vue * Update index.vue * wip * Update post-form-attaches.vue * Update note.vue * wip * clean up * Update notes.vue * wip * wip * Update ja-JP.yml * wip * wip * Update index.vue * wip * wip * wip * wip * wip * wip * wip * wip * Update default.vue * wip * Update _dark.json5 * wip * wip * wip * clean up * wip * wip * Update index.vue * Update test.vue * wip * wip * fix * wip * wip * wip * wip * clena yop * wip * wip * Update store.ts * Update messaging-room.vue * Update default.widgets.vue * fix * wip * wip * Update modal.vue * wip * Update os.ts * Update os.ts * Update deck.vue * Update init.ts * wip * Update ja-JP.yml * v-sizeは単にwindowのresizeを監視するだけで良いかもしれない * Update modal.vue * wip * Update tooltip.ts * wip * wip * wip * wip * wip * Update image-viewer.vue * wip * wip * Update style.scss * Update style.scss * Update visitor.vue * wip * Update init.ts * Update init.ts * wip * wip * Update visitor.vue * Update visitor.vue * Update visitor.vue * Update visitor.vue * wip * wip * Update modal.vue * Update header.vue * Update menu.vue * Update about.vue * Update about-misskey.vue * wip * wip * Update visitor.vue * Update tooltip.ts * wip * Update drive.vue * wip * Update style.scss * Update header.vue * wip * wip * Update users.user.vue * Update announcements.vue * wip * wip * wip * Update emojis.vue * wip * Update emojis.vue * Update style.scss * Update users.vue * wip * Update style.scss * wip * Update welcome.entrance.vue * Update radio.vue * Update size.ts * Update emoji-edit-dialog.vue * wip * Update emojis.vue * wip * Update emojis.vue * Update emojis.vue * Update emojis.vue * wip * wip * wip * wip * Update file-dialog.vue * wip * wip * Update token-generate-window.vue * Update notification-setting-window.vue * wip * wip * Update _error_.vue * Update ja-JP.yml * wip * wip * Update store.ts * Update emojis.vue * Update emojis.vue * Update emojis.vue * Update announcements.vue * Update store.ts * wip * Update page-editor.vue * wip * wip * Update modal.vue * wip * Update select-file.ts * Update timeline.vue * Update emojis.vue * Update os.ts * wip * Update user-select.vue * Update mfm.ts * Update get-file-info.ts * Update drive.vue * Update init.ts * Update mfm.ts * wip * wip * Update window.vue * Update note.vue * wip * wip * Update user-info.vue * wip * wip * wip * wip * wip * Update header.vue * Update header.vue * wip * Update explore.vue * wip * wip * wip * Update webpack.config.ts * wip * wip * wip * wip * wip * wip * Update autocomplete.ts * wip * wip * wip * Update toast.vue * wip * Update post-form-dialog.vue * wip * wip * wip * wip * wip * Update users.vue * wip * Update explore.vue * wip * wip * wip * Update package.json * wip * Update icon-dialog.vue * wip * wip * Update user-preview.ts * wip * wip * wip * wip * wip * Update instance.vue * Update user-name.vue * Update federation.vue * Update instance.vue * wip * wip * Update tag.vue * wip * wip * wip * wip * wip * Update instance.vue * wip * Update os.ts * Update os.ts * wip * wip * wip * Update router.ts * wip * Update init.ts * Update note.vue * Update messages.vue * wip * wip * wip * wip * wip * google * wip * wip * wip * wip * Update theme-editor.vue * wip * wip * Update room.vue * Update channel-editor.vue * wip * Update window.vue * Update window.vue * wip * Update window.vue * Update window.vue * wip * Update menu.vue * wip * wip * wip * wip * Update messaging-room.vue * wip * Update post-form.vue * Update default.widgets.vue * Update window.vue * wip
Diffstat (limited to 'src/client/components/mfm.ts')
-rw-r--r--src/client/components/mfm.ts189
1 files changed, 68 insertions, 121 deletions
diff --git a/src/client/components/mfm.ts b/src/client/components/mfm.ts
index 1dc8780389..791fd1b4e5 100644
--- a/src/client/components/mfm.ts
+++ b/src/client/components/mfm.ts
@@ -1,16 +1,18 @@
-import Vue, { VNode } from 'vue';
+import { VNode, defineComponent, h } from 'vue';
import { MfmForest } from '../../mfm/prelude';
import { parse, parsePlain } from '../../mfm/parse';
import MkUrl from './url.vue';
import MkLink from './link.vue';
import MkMention from './mention.vue';
+import MkEmoji from './emoji.vue';
import { concat } from '../../prelude/array';
import MkFormula from './formula.vue';
import MkCode from './code.vue';
import MkGoogle from './google.vue';
-import { host } from '../config';
+import { host } from '@/config';
+import { RouterLink } from 'vue-router';
-export default Vue.component('misskey-flavored-markdown', {
+export default defineComponent({
props: {
text: {
type: String,
@@ -41,7 +43,7 @@ export default Vue.component('misskey-flavored-markdown', {
},
},
- render(createElement) {
+ render() {
if (this.text == null || this.text == '') return;
const ast = (this.plain ? parsePlain : parse)(this.text);
@@ -53,67 +55,49 @@ export default Vue.component('misskey-flavored-markdown', {
if (!this.plain) {
const x = text.split('\n')
- .map(t => t == '' ? [createElement('br')] : [this._v(t), createElement('br')]); // NOTE: this._vはHACK SEE: https://github.com/syuilo/misskey/pull/6399#issuecomment-632820283
+ .map(t => t == '' ? [h('br')] : [t, h('br')]);
x[x.length - 1].pop();
return x;
} else {
- return [this._v(text.replace(/\n/g, ' '))];
+ return [text.replace(/\n/g, ' ')];
}
}
case 'bold': {
- return [createElement('b', genEl(token.children))];
+ return [h('b', genEl(token.children))];
}
case 'strike': {
- return [createElement('del', genEl(token.children))];
+ return [h('del', genEl(token.children))];
}
case 'italic': {
- return (createElement as any)('i', {
- attrs: {
- style: 'font-style: oblique;'
- },
+ return h('i', {
+ style: 'font-style: oblique;'
}, genEl(token.children));
}
case 'big': {
- return (createElement as any)('strong', {
- attrs: {
- style: `display: inline-block; font-size: 150%;`
- },
- directives: [this.$store.state.device.animatedMfm ? {
- name: 'animate-css',
- value: { classes: 'tada', iteration: 'infinite' }
- }: {}]
+ return h('strong', {
+ style: `display: inline-block; font-size: 150%;` + (this.$store.state.device.animatedMfm ? 'animation: anime-tada 1s linear infinite both;' : ''),
}, genEl(token.children));
}
case 'small': {
- return [createElement('small', {
- attrs: {
- style: 'opacity: 0.7;'
- },
+ return [h('small', {
+ style: 'opacity: 0.7;'
}, genEl(token.children))];
}
case 'center': {
- return [createElement('div', {
- attrs: {
- style: 'text-align:center;'
- }
+ return [h('div', {
+ style: 'text-align:center;'
}, genEl(token.children))];
}
case 'motion': {
- return (createElement as any)('span', {
- attrs: {
- style: 'display: inline-block;'
- },
- directives: [this.$store.state.device.animatedMfm ? {
- name: 'animate-css',
- value: { classes: 'rubberBand', iteration: 'infinite' }
- } : {}]
+ return h('span', {
+ style: 'display: inline-block;' + (this.$store.state.device.animatedMfm ? 'animation: anime-rubberBand 1s linear infinite both;' : ''),
}, genEl(token.children));
}
@@ -123,163 +107,126 @@ export default Vue.component('misskey-flavored-markdown', {
token.node.props.attr == 'alternate' ? 'alternate' :
'normal';
const style = this.$store.state.device.animatedMfm
- ? `animation: spin 1.5s linear infinite; animation-direction: ${direction};` : '';
- return (createElement as any)('span', {
- attrs: {
- style: 'display: inline-block;' + style
- },
+ ? `animation: anime-spin 1.5s linear infinite; animation-direction: ${direction};` : '';
+ return h('span', {
+ style: 'display: inline-block;' + style
}, genEl(token.children));
}
case 'jump': {
- return (createElement as any)('span', {
- attrs: {
- style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: jump 0.75s linear infinite;' : 'display: inline-block;'
- },
+ return h('span', {
+ style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: anime-jump 0.75s linear infinite;' : 'display: inline-block;'
}, genEl(token.children));
}
case 'flip': {
- return (createElement as any)('span', {
- attrs: {
- style: 'display: inline-block; transform: scaleX(-1);'
- },
+ return h('span', {
+ style: 'display: inline-block; transform: scaleX(-1);'
}, genEl(token.children));
}
case 'url': {
- return [createElement(MkUrl, {
+ return [h(MkUrl, {
key: Math.random(),
- props: {
- url: token.node.props.url,
- rel: 'nofollow noopener',
- },
+ url: token.node.props.url,
+ rel: 'nofollow noopener',
})];
}
case 'link': {
- return [createElement(MkLink, {
+ return [h(MkLink, {
key: Math.random(),
- props: {
- url: token.node.props.url,
- rel: 'nofollow noopener',
- },
+ url: token.node.props.url,
+ rel: 'nofollow noopener',
}, genEl(token.children))];
}
case 'mention': {
- return [createElement(MkMention, {
+ return [h(MkMention, {
key: Math.random(),
- props: {
- host: (token.node.props.host == null && this.author && this.author.host != null ? this.author.host : token.node.props.host) || host,
- username: token.node.props.username
- }
+ host: (token.node.props.host == null && this.author && this.author.host != null ? this.author.host : token.node.props.host) || host,
+ username: token.node.props.username
})];
}
case 'hashtag': {
- return [createElement('router-link', {
+ return [h(RouterLink, {
key: Math.random(),
- attrs: {
- to: this.isNote ? `/tags/${encodeURIComponent(token.node.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.node.props.hashtag)}`,
- style: 'color:var(--hashtag);'
- }
+ to: this.isNote ? `/tags/${encodeURIComponent(token.node.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.node.props.hashtag)}`,
+ style: 'color:var(--hashtag);'
}, `#${token.node.props.hashtag}`)];
}
case 'blockCode': {
- return [createElement(MkCode, {
+ return [h(MkCode, {
key: Math.random(),
- props: {
- code: token.node.props.code,
- lang: token.node.props.lang,
- }
+ code: token.node.props.code,
+ lang: token.node.props.lang,
})];
}
case 'inlineCode': {
- return [createElement(MkCode, {
+ return [h(MkCode, {
key: Math.random(),
- props: {
- code: token.node.props.code,
- lang: token.node.props.lang,
- inline: true
- }
+ code: token.node.props.code,
+ lang: token.node.props.lang,
+ inline: true
})];
}
case 'quote': {
- if (this.shouldBreak) {
- return [createElement('div', {
- attrs: {
- class: 'quote'
- }
+ if (!this.nowrap) {
+ return [h('div', {
+ class: 'quote'
}, genEl(token.children))];
} else {
- return [createElement('span', {
- attrs: {
- class: 'quote'
- }
+ return [h('span', {
+ class: 'quote'
}, genEl(token.children))];
}
}
case 'title': {
- return [createElement('div', {
- attrs: {
- class: 'title'
- }
+ return [h('div', {
+ class: 'title'
}, genEl(token.children))];
}
case 'emoji': {
- return [createElement('mk-emoji', {
+ return [h(MkEmoji, {
key: Math.random(),
- attrs: {
- emoji: token.node.props.emoji,
- name: token.node.props.name
- },
- props: {
- customEmojis: this.customEmojis,
- normal: this.plain
- }
+ emoji: token.node.props.emoji,
+ name: token.node.props.name,
+ customEmojis: this.customEmojis,
+ normal: this.plain
})];
}
case 'mathInline': {
- //const MkFormula = () => import('./formula.vue').then(m => m.default);
- return [createElement(MkFormula, {
+ return [h(MkFormula, {
key: Math.random(),
- props: {
- formula: token.node.props.formula,
- block: false
- }
+ formula: token.node.props.formula,
+ block: false
})];
}
case 'mathBlock': {
- //const MkFormula = () => import('./formula.vue').then(m => m.default);
- return [createElement(MkFormula, {
+ return [h(MkFormula, {
key: Math.random(),
- props: {
- formula: token.node.props.formula,
- block: true
- }
+ formula: token.node.props.formula,
+ block: true
})];
}
case 'search': {
- //const MkGoogle = () => import('./google.vue').then(m => m.default);
- return [createElement(MkGoogle, {
+ return [h(MkGoogle, {
key: Math.random(),
- props: {
- q: token.node.props.query
- }
+ q: token.node.props.query
})];
}
default: {
- console.log('unrecognized ast type:', token.node.type);
+ console.error('unrecognized ast type:', token.node.type);
return [];
}
@@ -287,6 +234,6 @@ export default Vue.component('misskey-flavored-markdown', {
}));
// Parse ast to DOM
- return createElement('span', genEl(ast));
+ return h('span', genEl(ast));
}
});