mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-10-01 04:56:59 -05:00
Merge branch 'dev' into feat/password-editing
This commit is contained in:
36
src/composables/customSeoMeta.ts
Normal file
36
src/composables/customSeoMeta.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { UseSeoMetaInput } from '@unhead/vue';
|
||||
|
||||
export type CustomSeoMetaOptions = UseSeoMetaInput & {
|
||||
subsection?: string;
|
||||
};
|
||||
|
||||
export default function (args?: CustomSeoMetaOptions) {
|
||||
let newTitleTemplate = '';
|
||||
|
||||
switch (args?.subsection) {
|
||||
case ('account'): {
|
||||
newTitleTemplate = 'Account | Pretendo Network';
|
||||
break;
|
||||
}
|
||||
case ('terms'): {
|
||||
newTitleTemplate = 'Terms | Pretendo Network';
|
||||
break;
|
||||
}
|
||||
case ('blog'): {
|
||||
newTitleTemplate = 'Blog | Pretendo Network';
|
||||
break;
|
||||
}
|
||||
case ('docs'): {
|
||||
newTitleTemplate = 'Docs | Pretendo Network';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
newTitleTemplate = 'Pretendo Network';
|
||||
}
|
||||
}
|
||||
|
||||
const newTitle = args?.title ? `${args?.title} | ${newTitleTemplate}` : newTitleTemplate;
|
||||
|
||||
useHead({ title: newTitle });
|
||||
useSeoMeta({ ...args, title: newTitle, ogTitle: newTitle, twitterTitle: newTitle, ogDescription: args?.description, twitterDescription: args?.description, twitterImage: args?.ogImage });
|
||||
}
|
||||
@@ -3,9 +3,11 @@ import { watchImmediate } from '@vueuse/core';
|
||||
import DefaultLayout from './layouts/default.vue';
|
||||
const { error } = defineProps<{ error: any }>();
|
||||
|
||||
watchImmediate([error], () => {
|
||||
console.error(error);
|
||||
});
|
||||
if (import.meta.client) {
|
||||
watchImmediate([() => error], () => {
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
titleTemplate: (titleChunk) => {
|
||||
return titleChunk ? `${titleChunk} | Pretendo Network` : 'Pretendo Network';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
const path = useRoute().fullPath;
|
||||
|
||||
const isSidebarOpen = ref(false);
|
||||
|
||||
useHead({
|
||||
titleTemplate: (titleChunk) => {
|
||||
return titleChunk
|
||||
? `${titleChunk} | Docs | Pretendo Network`
|
||||
: 'Docs | Pretendo Network';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
"nickname": "昵称",
|
||||
"birthDate": "生日",
|
||||
"gender": "性别",
|
||||
"country": "国家/地区",
|
||||
"country": "国家",
|
||||
"timezone": "时区",
|
||||
"serverEnv": "服务器环境",
|
||||
"production": "生产环境",
|
||||
@@ -244,7 +244,8 @@
|
||||
"no_newsletter_notice": "电子报告目前不可用,请稍后再来查看。",
|
||||
"userSettings": "用户设置",
|
||||
"no_signins_notice": "目前没有任何登录历史。请稍后再试!",
|
||||
"no_edit_from_dashboard": "目前无法从网站修改 PNID 设置。请通过已绑定的主机上修改用户设置。"
|
||||
"no_edit_from_dashboard": "目前无法从网站修改 PNID 设置。请通过已绑定的主机上修改用户设置。",
|
||||
"region": "地区"
|
||||
},
|
||||
"upgrade": "升级账号",
|
||||
"unavailable": "无法使用",
|
||||
@@ -309,7 +310,7 @@
|
||||
"clickToSet": "点击设置",
|
||||
"favorite": "设为最爱",
|
||||
"sharing": "共享",
|
||||
"copying": "复制中",
|
||||
"copying": "允许复制",
|
||||
"save": "保存",
|
||||
"saveCaption": "保存你的 Mii 虚拟形象会删除之前的 Mii 虚拟形象。",
|
||||
"noCanvas": "您的浏览器不支持 canvas 元素。",
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
"profile": "個人檔案",
|
||||
"birthDate": "生日",
|
||||
"gender": "性別",
|
||||
"country": "國家/地區",
|
||||
"country": "國家",
|
||||
"timezone": "時區",
|
||||
"serverEnv": "伺服器環境",
|
||||
"production": "生產",
|
||||
@@ -204,7 +204,8 @@
|
||||
"passwordPrompt": "輸入你的 PNID 密碼以下載 Cemu 檔案",
|
||||
"no_signins_notice": "登入歷史紀錄目前未記錄。請稍後再來查看!",
|
||||
"no_newsletter_notice": "電子報告目前無法使用。請稍後再來查看!",
|
||||
"no_edit_from_dashboard": "目前無法從網站編輯 PNID 設定。請通過已連結的主機上編輯使用者設定。"
|
||||
"no_edit_from_dashboard": "目前無法從網站編輯 PNID 設定。請通過已連結的主機上編輯使用者設定。",
|
||||
"region": "地區"
|
||||
},
|
||||
"upgrade": "升級帳號",
|
||||
"unavailable": "無法使用",
|
||||
@@ -307,7 +308,7 @@
|
||||
"miiEditor": {
|
||||
"birthday": "生日",
|
||||
"clickToSet": "點觸設定",
|
||||
"copying": "複製中",
|
||||
"copying": "允許複製",
|
||||
"corruptedData": "找到已損壞的 Mii 資料。是否要從頭開始?",
|
||||
"creator": "創作者",
|
||||
"favorite": "設為最愛",
|
||||
|
||||
@@ -48,6 +48,8 @@ const { execute, isLoading } = useAsync({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
customSeoMeta({ subsection: 'account', title: 'Forgot password' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -155,9 +155,7 @@ const { execute: executeUnlinkDiscord, isLoading: isLoadingUnlink } = useAsync({
|
||||
}
|
||||
});
|
||||
|
||||
useHead({
|
||||
title: `Account`
|
||||
});
|
||||
customSeoMeta({ subsection: 'account' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -167,15 +165,27 @@ useHead({
|
||||
>
|
||||
<div class="account-sidebar">
|
||||
<div class="user">
|
||||
<a
|
||||
href="/account/miieditor"
|
||||
class="mii"
|
||||
>
|
||||
<img
|
||||
:src="profile.mii?.imageUrl"
|
||||
alt="Mii image"
|
||||
<div class="mii-wrapper">
|
||||
<a
|
||||
href="/account/miieditor"
|
||||
class="mii"
|
||||
>
|
||||
</a>
|
||||
<img
|
||||
:src="profile.mii?.imageUrl"
|
||||
alt="Mii image"
|
||||
>
|
||||
</a>
|
||||
<a
|
||||
class="edit-button"
|
||||
href="/account/miieditor"
|
||||
>
|
||||
<Icon
|
||||
name="ph:pencil"
|
||||
size="20"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<p class="miiname">
|
||||
{{ profile.mii?.name }}
|
||||
</p>
|
||||
@@ -641,36 +651,41 @@ useHead({
|
||||
border-color: #5aff15;
|
||||
}
|
||||
|
||||
.account-sidebar .user .mii-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.account-sidebar .user a.mii {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
overflow: hidden;
|
||||
border-radius: 100%;
|
||||
border-radius: 9999px;
|
||||
background: var(--bg-shade-3);
|
||||
}
|
||||
.account-sidebar .user a.mii::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:
|
||||
no-repeat center/50% url("@/public/assets/images/edit.svg"),
|
||||
rgba(55, 60, 101, 0.7);
|
||||
opacity: 0;
|
||||
transition: opacity 150ms;
|
||||
}
|
||||
.account-sidebar .user a.mii:hover::after {
|
||||
opacity: 1;
|
||||
.account-sidebar .user a.mii:hover,
|
||||
.account-sidebar .user .mii-wrapper a.edit-button:hover,
|
||||
.account-sidebar .user:has(a.edit-button:hover) a.mii,
|
||||
.account-sidebar .user:has(a.mii:hover) a.edit-button {
|
||||
background: var(--bg-shade-4);
|
||||
}
|
||||
|
||||
.account-sidebar .user .mii {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.account-sidebar .user .mii-wrapper a.edit-button {
|
||||
color: inherit;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg-shade-3);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border: 2px solid var(--bg-shade-1);
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.account-sidebar .buttons {
|
||||
display: grid;
|
||||
grid-auto-flow: row;
|
||||
|
||||
@@ -47,6 +47,8 @@ const { execute, isLoading } = useAsync({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
customSeoMeta({ subsection: 'account', title: 'Login' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -15,9 +15,7 @@ definePageMeta({
|
||||
|
||||
const { data: profile } = await useApiFetch('/api/auth/me');
|
||||
|
||||
useHead({
|
||||
title: 'Mii Editor | Pretendo Network'
|
||||
});
|
||||
customSeoMeta({ subsection: 'account', title: 'Mii Editor' });
|
||||
|
||||
const beforeUnload = (e: BeforeUnloadEvent) => {
|
||||
e?.preventDefault();
|
||||
|
||||
@@ -55,6 +55,8 @@ const { execute, isLoading } = useAsync({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
customSeoMeta({ subsection: 'account', title: 'Register' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -30,6 +30,8 @@ const { execute, isLoading } = useAsync({
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
customSeoMeta({ subsection: 'account', title: 'Reset Password' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -81,10 +81,7 @@ function hasSubscription(priceId: string) {
|
||||
profile.value?.stripeTier && priceId === profile.value.stripeTier.priceId
|
||||
);
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `Upgrade`
|
||||
});
|
||||
customSeoMeta({ subsection: 'account', title: 'Upgrade' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -8,16 +8,11 @@ if (!post.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `${post.value.title} | Blog`,
|
||||
meta: [
|
||||
{ property: 'description', content: post.value.caption },
|
||||
{ property: 'og:description', content: post.value.caption },
|
||||
{ property: 'og:image', content: post.value.cover_image },
|
||||
{ property: 'og:image:alt', content: '' },
|
||||
{ name: 'twitter:description', content: post.value.caption },
|
||||
{ name: 'twitter:image', content: post.value.cover_image }
|
||||
]
|
||||
customSeoMeta({
|
||||
subsection: 'blog',
|
||||
title: post.value.title,
|
||||
description: post.value.caption,
|
||||
ogImage: post.value.cover_image
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Blog'
|
||||
});
|
||||
customSeoMeta({ subsection: 'blog' });
|
||||
/* eslint-disable vue/no-v-html -- we might wanna avoid this by rewriting the locales to use variables */
|
||||
const { data: allPosts } = await useAsyncData('blog', () => queryCollection('blog').all());
|
||||
|
||||
const posts = computed(() => allPosts.value?.filter(p => !p.path.startsWith('/blog/_')).sort((a, b) => {
|
||||
return new Date(b.date).getTime() - new Date(a.date).getTime();
|
||||
}));
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -7,15 +7,10 @@ const { data: doc } = await useAsyncData(`docs-${slug}`, () => {
|
||||
if (!doc.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `${doc.value.title}`,
|
||||
meta: [
|
||||
{ property: 'description', content: doc.value.description },
|
||||
{ property: 'og:description', content: doc.value.description },
|
||||
{ property: 'og:image:alt', content: '' },
|
||||
{ name: 'twitter:description', content: doc.value.description }
|
||||
]
|
||||
customSeoMeta({
|
||||
subsection: 'docs',
|
||||
title: doc.value.title,
|
||||
description: doc.value.description
|
||||
});
|
||||
|
||||
definePageMeta({
|
||||
|
||||
@@ -8,14 +8,10 @@ if (!error.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `${error.value.code} | Docs`,
|
||||
meta: [
|
||||
{ property: 'description', content: error.value.message },
|
||||
{ property: 'og:description', content: error.value.message },
|
||||
{ property: 'og:image:alt', content: '' },
|
||||
{ name: 'twitter:description', content: error.value.message }
|
||||
]
|
||||
customSeoMeta({
|
||||
subsection: 'docs',
|
||||
title: error.value.code,
|
||||
description: error.value.message
|
||||
});
|
||||
|
||||
definePageMeta({
|
||||
|
||||
@@ -36,25 +36,10 @@ const { data: searchResults } = await useAsyncData(
|
||||
);
|
||||
const results = computed(() => searchResults.value ?? []);
|
||||
|
||||
useHead({
|
||||
customSeoMeta({
|
||||
subsection: 'docs',
|
||||
title: 'Search',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Got an error code? Find solutions here.'
|
||||
},
|
||||
{
|
||||
name: 'og:description',
|
||||
content:
|
||||
'Got an error code? Find solutions here.'
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content:
|
||||
'Got an error code? Find solutions here.'
|
||||
}
|
||||
]
|
||||
description: 'Got an error code? Find solutions here.'
|
||||
});
|
||||
|
||||
definePageMeta({
|
||||
|
||||
@@ -1,23 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
|
||||
customSeoMeta({
|
||||
subsection: 'docs',
|
||||
title: 'Install',
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
},
|
||||
{
|
||||
name: 'og:description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
}
|
||||
]
|
||||
description: 'Learn how to set up Pretendo Network on a variety of consoles and emulators.'
|
||||
});
|
||||
|
||||
definePageMeta({
|
||||
|
||||
@@ -1,23 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
useHead({
|
||||
meta: [
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
},
|
||||
{
|
||||
name: 'og:description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content:
|
||||
'Learn how to set up Pretendo on a variety of consoles and emulators.'
|
||||
}
|
||||
]
|
||||
customSeoMeta({
|
||||
subsection: 'docs',
|
||||
description: 'Learn how to set up Pretendo Network on a variety of consoles and emulators.'
|
||||
});
|
||||
|
||||
definePageMeta({
|
||||
|
||||
@@ -32,6 +32,8 @@ function arraySplit<T>(array: Array<T>, groupCount: number): Array<Array<T>> {
|
||||
function titleSuffixHandler(path: string) {
|
||||
return te(path) ? t(path) : null;
|
||||
}
|
||||
|
||||
customSeoMeta();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -4,6 +4,7 @@ useHead({
|
||||
link: [{ rel: 'stylesheet', href: 'https://use.typekit.net/gok5tsu.css' }]
|
||||
});
|
||||
|
||||
customSeoMeta();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
const { t } = useI18n();
|
||||
|
||||
customSeoMeta({
|
||||
title: t('progressPage.title'),
|
||||
description: t('progressPage.description')
|
||||
});
|
||||
|
||||
const progress = await useFetch('/api/progress');
|
||||
const projects = computed(() => progress.data.value?.items ?? []);
|
||||
const donations = computed(() => progress.data.value?.donations);
|
||||
|
||||
@@ -8,14 +8,10 @@ if (!termContent.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: `${termContent.value.title} | Terms`,
|
||||
meta: [
|
||||
{ property: 'description', content: termContent.value.description },
|
||||
{ property: 'og:description', content: termContent.value.description },
|
||||
{ property: 'og:image:alt', content: '' },
|
||||
{ name: 'twitter:description', content: termContent.value.description }
|
||||
]
|
||||
customSeoMeta({
|
||||
subsection: 'terms',
|
||||
title: termContent.value.title,
|
||||
description: termContent.value.description
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user