From 1a464eb0af62d1aff57d0b8b00f75f8521e538ae Mon Sep 17 00:00:00 2001 From: yukineko <27853966+hideki0403@users.noreply.github.com> Date: Thu, 4 Jan 2024 00:01:49 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20components/global=E5=86=85=E3=81=AE?= =?UTF-8?q?=E5=9E=8B=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=8C=E5=87=BA=E3=81=A6?= =?UTF-8?q?=E3=81=84=E3=82=8B=E7=AE=87=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/MkImgWithBlurhash.vue | 2 +- .../src/components/global/MkAvatar.vue | 9 ++++-- .../src/components/global/MkCustomEmoji.vue | 2 +- .../global/MkMisskeyFlavoredMarkdown.ts | 28 ++++++++++--------- .../components/global/MkPageHeader.tabs.vue | 12 +++++--- .../frontend/src/components/global/MkTime.vue | 2 +- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/packages/frontend/src/components/MkImgWithBlurhash.vue b/packages/frontend/src/components/MkImgWithBlurhash.vue index 942861e1f4..03f5106aa3 100644 --- a/packages/frontend/src/components/MkImgWithBlurhash.vue +++ b/packages/frontend/src/components/MkImgWithBlurhash.vue @@ -73,7 +73,7 @@ const props = withDefaults(defineProps<{ leaveFromClass?: string; } | null; src?: string | null; - hash?: string; + hash?: string | null; alt?: string | null; title?: string | null; height?: number; diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue index af5b6e44f5..64d0e4230e 100644 --- a/packages/frontend/src/components/global/MkAvatar.vue +++ b/packages/frontend/src/components/global/MkAvatar.vue @@ -81,9 +81,11 @@ const bound = computed(() => props.link ? { to: userPage(props.user), target: props.target } : {}); -const url = computed(() => (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) - ? getStaticImageUrl(props.user.avatarUrl) - : props.user.avatarUrl); +const url = computed(() => { + if (!props.user.avatarUrl) return null; + if (defaultStore.state.disableShowingAnimatedImages || defaultStore.state.dataSaver.avatar) return getStaticImageUrl(props.user.avatarUrl); + return props.user.avatarUrl; +}); function onClick(ev: MouseEvent): void { if (props.link) return; @@ -109,6 +111,7 @@ function getDecorationOffset(decoration: Omit(); watch(() => props.user.avatarBlurhash, () => { + if (!props.user.avatarBlurhash) return; color.value = extractAvgColorFromBlurhash(props.user.avatarBlurhash); }, { immediate: true, diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue index a9643d68ca..ec47d07c0b 100644 --- a/packages/frontend/src/components/global/MkCustomEmoji.vue +++ b/packages/frontend/src/components/global/MkCustomEmoji.vue @@ -55,7 +55,7 @@ const rawUrl = computed(() => { }); const url = computed(() => { - if (rawUrl.value == null) return null; + if (rawUrl.value == null) return undefined; const proxied = (rawUrl.value.startsWith('/emoji/') || (props.useOriginalSize && isLocal.value)) diff --git a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts index 650c79dff7..baee969ac4 100644 --- a/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts +++ b/packages/frontend/src/components/global/MkMisskeyFlavoredMarkdown.ts @@ -19,6 +19,7 @@ import MkA from '@/components/global/MkA.vue'; import { host } from '@/config.js'; import { defaultStore } from '@/store.js'; import { nyaize as doNyaize } from '@/scripts/nyaize.js'; +import { safeParseFloat } from '@/scripts/safe-parse.js'; const QUOTE_STYLE = ` display: block; @@ -35,7 +36,7 @@ type MfmProps = { nowrap?: boolean; author?: Misskey.entities.UserLite; isNote?: boolean; - emojiUrls?: string[]; + emojiUrls?: Record; rootScale?: number; nyaize?: boolean | 'respect'; parsedNodes?: mfm.MfmNode[] | null; @@ -57,8 +58,9 @@ export default function(props: MfmProps, context: SetupContext) { const rootAst = props.parsedNodes ?? (props.plain ? mfm.parseSimple : mfm.parse)(props.text); - const validTime = (t: string | null | undefined) => { + const validTime = (t: string | boolean | null | undefined) => { if (t == null) return null; + if (typeof t === 'boolean') return null; return t.match(/^[0-9.]+s$/) ? t : null; }; @@ -217,14 +219,14 @@ export default function(props: MfmProps, context: SetupContext) { return h(MkSparkle, {}, genEl(token.children, scale)); } case 'rotate': { - const degrees = parseFloat(token.props.args.deg ?? '90'); + const degrees = safeParseFloat(token.props.args.deg) ?? 90; style = `transform: rotate(${degrees}deg); transform-origin: center center;`; break; } case 'position': { if (!defaultStore.state.advancedMfm) break; - const x = parseFloat(token.props.args.x ?? '0'); - const y = parseFloat(token.props.args.y ?? '0'); + const x = safeParseFloat(token.props.args.x) ?? 0; + const y = safeParseFloat(token.props.args.y) ?? 0; style = `transform: translateX(${x}em) translateY(${y}em);`; break; } @@ -233,21 +235,21 @@ export default function(props: MfmProps, context: SetupContext) { style = ''; break; } - const x = Math.min(parseFloat(token.props.args.x ?? '1'), 5); - const y = Math.min(parseFloat(token.props.args.y ?? '1'), 5); + const x = Math.min(safeParseFloat(token.props.args.x) ?? 1, 5); + const y = Math.min(safeParseFloat(token.props.args.y) ?? 1, 5); style = `transform: scale(${x}, ${y});`; scale = scale * Math.max(x, y); break; } case 'fg': { let color = token.props.args.color; - if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00'; + if (typeof color !== 'string' || !/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00'; style = `color: #${color}; overflow-wrap: anywhere;`; break; } case 'bg': { let color = token.props.args.color; - if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00'; + if (typeof color !== 'string' || !/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00'; style = `background-color: #${color}; overflow-wrap: anywhere;`; break; } @@ -289,7 +291,8 @@ export default function(props: MfmProps, context: SetupContext) { return h('span', { onClick(ev: MouseEvent): void { ev.stopPropagation(); ev.preventDefault(); - context.emit('clickEv', token.props.args.ev ?? ''); + const clickEv = typeof token.props.args.ev === 'string' ? token.props.args.ev : ''; + context.emit('clickEv', clickEv); } }, genEl(token.children, scale)); } } @@ -350,7 +353,7 @@ export default function(props: MfmProps, context: SetupContext) { return [h(MkCode, { key: Math.random(), code: token.props.code, - lang: token.props.lang, + lang: token.props.lang ?? undefined, })]; } @@ -394,8 +397,7 @@ export default function(props: MfmProps, context: SetupContext) { return [h(MkCustomEmoji, { key: Math.random(), name: token.props.name, - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - url: props.emojiUrls ? props.emojiUrls[token.props.name] : null, + url: props.emojiUrls && props.emojiUrls[token.props.name], normal: props.plain, host: props.author.host, useOriginalSize: scale >= 2.5, diff --git a/packages/frontend/src/components/global/MkPageHeader.tabs.vue b/packages/frontend/src/components/global/MkPageHeader.tabs.vue index 24b92cb83a..a12a5f739d 100644 --- a/packages/frontend/src/components/global/MkPageHeader.tabs.vue +++ b/packages/frontend/src/components/global/MkPageHeader.tabs.vue @@ -38,6 +38,7 @@ SPDX-License-Identifier: AGPL-3.0-only