open links in abuse comment in new window (#13381)

* feat: changing MkA behavior from MkMFM

* chore: open links in abuse comment in new window

* docs(changelog): 通報のコメント内のリンクをクリックした際、ウィンドウで開くように

* chore: use inject instead of prop drilling

* Revert "chore: use inject instead of prop drilling"

This reverts commit b4dd14eacf59c8079676aa6ab019fece67496d79.
This commit is contained in:
anatawa12 2024-04-27 21:24:39 +09:00 committed by GitHub
parent fe1172fbb6
commit 8e8ee2ac73
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 24 additions and 4 deletions

View file

@ -36,6 +36,7 @@
- 引用したいートのURLをコピーしリプライ投稿画面にペーストして添付することで達成できます - 引用したいートのURLをコピーしリプライ投稿画面にペーストして添付することで達成できます
- Enhance: フォローするかどうかの確認ダイアログを出せるように - Enhance: フォローするかどうかの確認ダイアログを出せるように
- Enhance: Playを手動でリロードできるように - Enhance: Playを手動でリロードできるように
- Enhance: 通報のコメント内のリンクをクリックした際、ウィンドウで開くように
- Chore: AiScriptを0.18.0にバージョンアップ - Chore: AiScriptを0.18.0にバージョンアップ
- Fix: 一部のページ内リンクが正しく動作しない問題を修正 - Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: 周年の実績が閏年を考慮しない問題を修正 - Fix: 周年の実績が閏年を考慮しない問題を修正

View file

@ -20,7 +20,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
<div class="detail"> <div class="detail">
<div> <div>
<Mfm :text="report.comment"/> <Mfm :text="report.comment" :linkBehavior="'window'"/>
</div> </div>
<hr/> <hr/>
<div>{{ i18n.ts.reporter }}: <MkA :to="`/admin/user/${report.reporter.id}`" class="_link" :behavior="'window'">@{{ report.reporter.username }}</MkA></div> <div>{{ i18n.ts.reporter }}: <MkA :to="`/admin/user/${report.reporter.id}`" class="_link" :behavior="'window'">@{{ report.reporter.username }}</MkA></div>

View file

@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<component <component
:is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel ?? 'nofollow noopener'" :target="target" :is="self ? 'MkA' : 'a'" ref="el" style="word-break: break-all;" class="_link" :[attr]="self ? url.substring(local.length) : url" :rel="rel ?? 'nofollow noopener'" :target="target"
:behavior="props.behavior"
:title="url" :title="url"
> >
<slot></slot> <slot></slot>
@ -19,10 +20,12 @@ import { url as local } from '@/config.js';
import { useTooltip } from '@/scripts/use-tooltip.js'; import { useTooltip } from '@/scripts/use-tooltip.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { isEnabledUrlPreview } from '@/instance.js'; import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
url: string; url: string;
rel?: null | string; rel?: null | string;
behavior?: MkABehavior;
}>(), { }>(), {
}); });

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<MkA v-user-preview="canonical" :class="[$style.root, { [$style.isMe]: isMe }]" :to="url" :style="{ background: bgCss }"> <MkA v-user-preview="canonical" :class="[$style.root, { [$style.isMe]: isMe }]" :to="url" :style="{ background: bgCss }" :behavior="behavior">
<img :class="$style.icon" :src="avatarUrl" alt=""> <img :class="$style.icon" :src="avatarUrl" alt="">
<span> <span>
<span>@{{ username }}</span> <span>@{{ username }}</span>
@ -21,10 +21,12 @@ import { host as localHost } from '@/config.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { getStaticImageUrl } from '@/scripts/media-proxy.js'; import { getStaticImageUrl } from '@/scripts/media-proxy.js';
import { MkABehavior } from '@/components/global/MkA.vue';
const props = defineProps<{ const props = defineProps<{
username: string; username: string;
host: string; host: string;
behavior?: MkABehavior;
}>(); }>();
const canonical = props.host === localHost ? `@${props.username}` : `@${props.username}@${toUnicode(props.host)}`; const canonical = props.host === localHost ? `@${props.username}` : `@${props.username}@${toUnicode(props.host)}`;

View file

@ -9,6 +9,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</a> </a>
</template> </template>
<script lang="ts">
export type MkABehavior = 'window' | 'browser' | null;
</script>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, shallowRef } from 'vue'; import { computed, shallowRef } from 'vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -20,12 +24,14 @@ import { useRouter } from '@/router/supplier.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
to: string; to: string;
activeClass?: null | string; activeClass?: null | string;
behavior?: null | 'window' | 'browser'; behavior?: MkABehavior;
}>(), { }>(), {
activeClass: null, activeClass: null,
behavior: null, behavior: null,
}); });
const linkBehaviour = props.behavior;
const el = shallowRef<HTMLElement>(); const el = shallowRef<HTMLElement>();
defineExpose({ $el: el }); defineExpose({ $el: el });

View file

@ -16,7 +16,7 @@ import MkCode from '@/components/MkCode.vue';
import MkCodeInline from '@/components/MkCodeInline.vue'; import MkCodeInline from '@/components/MkCodeInline.vue';
import MkGoogle from '@/components/MkGoogle.vue'; import MkGoogle from '@/components/MkGoogle.vue';
import MkSparkle from '@/components/MkSparkle.vue'; import MkSparkle from '@/components/MkSparkle.vue';
import MkA from '@/components/global/MkA.vue'; import MkA, {MkABehavior} from '@/components/global/MkA.vue';
import { host } from '@/config.js'; import { host } from '@/config.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { nyaize as doNyaize } from '@/scripts/nyaize.js'; import { nyaize as doNyaize } from '@/scripts/nyaize.js';
@ -43,6 +43,7 @@ type MfmProps = {
parsedNodes?: mfm.MfmNode[] | null; parsedNodes?: mfm.MfmNode[] | null;
enableEmojiMenu?: boolean; enableEmojiMenu?: boolean;
enableEmojiMenuReaction?: boolean; enableEmojiMenuReaction?: boolean;
linkBehavior?: MkABehavior;
}; };
type MfmEvents = { type MfmEvents = {
@ -342,6 +343,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
key: Math.random(), key: Math.random(),
url: token.props.url, url: token.props.url,
rel: 'nofollow noopener', rel: 'nofollow noopener',
behavior: props.linkBehavior,
})]; })];
} }
@ -350,6 +352,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
key: Math.random(), key: Math.random(),
url: token.props.url, url: token.props.url,
rel: 'nofollow noopener', rel: 'nofollow noopener',
behavior: props.linkBehavior,
}, genEl(token.children, scale, true))]; }, genEl(token.children, scale, true))];
} }
@ -358,6 +361,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
key: Math.random(), key: Math.random(),
host: (token.props.host == null && props.author && props.author.host != null ? props.author.host : token.props.host) ?? host, host: (token.props.host == null && props.author && props.author.host != null ? props.author.host : token.props.host) ?? host,
username: token.props.username, username: token.props.username,
behavior: props.linkBehavior,
})]; })];
} }
@ -366,6 +370,7 @@ export default function (props: MfmProps, { emit }: { emit: SetupContext<MfmEven
key: Math.random(), key: Math.random(),
to: isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/user-tags/${encodeURIComponent(token.props.hashtag)}`, to: isNote ? `/tags/${encodeURIComponent(token.props.hashtag)}` : `/user-tags/${encodeURIComponent(token.props.hashtag)}`,
style: 'color:var(--hashtag);', style: 'color:var(--hashtag);',
behavior: props.linkBehavior,
}, `#${token.props.hashtag}`)]; }, `#${token.props.hashtag}`)];
} }

View file

@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<component <component
:is="self ? 'MkA' : 'a'" ref="el" :class="$style.root" class="_link" :[attr]="self ? props.url.substring(local.length) : props.url" :rel="rel ?? 'nofollow noopener'" :target="target" :is="self ? 'MkA' : 'a'" ref="el" :class="$style.root" class="_link" :[attr]="self ? props.url.substring(local.length) : props.url" :rel="rel ?? 'nofollow noopener'" :target="target"
:behavior = "props.behavior"
@contextmenu.stop="() => {}" @contextmenu.stop="() => {}"
> >
<template v-if="!self"> <template v-if="!self">
@ -31,11 +32,13 @@ import * as os from '@/os.js';
import { useTooltip } from '@/scripts/use-tooltip.js'; import { useTooltip } from '@/scripts/use-tooltip.js';
import { safeURIDecode } from '@/scripts/safe-uri-decode.js'; import { safeURIDecode } from '@/scripts/safe-uri-decode.js';
import { isEnabledUrlPreview } from '@/instance.js'; import { isEnabledUrlPreview } from '@/instance.js';
import { MkABehavior } from '@/components/global/MkA.vue';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
url: string; url: string;
rel?: string; rel?: string;
showUrlPreview?: boolean; showUrlPreview?: boolean;
behavior?: MkABehavior;
}>(), { }>(), {
showUrlPreview: true, showUrlPreview: true,
}); });