[FEAT] Fix vue warn

This commit is contained in:
2025-11-26 17:16:52 +01:00
parent 09c77f5414
commit accea99408
6 changed files with 148 additions and 137 deletions

View File

@@ -1,24 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
import { useStructuredData } from '../composables/useStructuredData'; import { useStructuredData } from '../composables/useStructuredData';
const { addBreadcrumbSchema } = useStructuredData(); const { addBreadcrumbSchema } = useStructuredData();
onMounted(() => { // Set SEO synchronously
useSEO({ useSEO({
title: 'About Us - Our Mission & Story', title: 'About Us - Our Mission & Story',
description: 'Learn about Spritesheet Generator, a free tool designed to help game developers and artists streamline their workflow with optimized spritesheet creation.', description: 'Learn about Spritesheet Generator, a free tool designed to help game developers and artists streamline their workflow with optimized spritesheet creation.',
url: '/about', url: '/about',
type: 'website', type: 'website',
keywords: 'about spritesheet generator, game development tools, open source sprite editor' keywords: 'about spritesheet generator, game development tools, open source sprite editor'
});
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'About Us', url: '/about' }
]);
}); });
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'About Us', url: '/about' }
]);
</script> </script>
<template> <template>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch } from 'vue'; import { ref, onMounted, watch, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { useBlog, type BlogPost } from '../composables/useBlog'; import { useBlog, type BlogPost } from '../composables/useBlog';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
@@ -13,43 +13,61 @@
const post = ref<BlogPost | undefined>(undefined); const post = ref<BlogPost | undefined>(undefined);
const renderedContent = ref(''); const renderedContent = ref('');
const slug = computed(() => route.params.slug as string);
// Initialize with default SEO (will be updated when post loads)
useSEO({
title: 'Blog Post',
description: 'Read our latest article about spritesheet generation and game development.',
url: `/blog/${slug.value}`,
type: 'article',
keywords: 'sprite sheet, game development, blog'
});
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog' },
{ name: 'Article', url: `/blog/${slug.value}` }
]);
onMounted(async () => { onMounted(async () => {
const slug = route.params.slug as string; post.value = await getPost(slug.value);
post.value = await getPost(slug);
if (post.value) { if (post.value) {
renderedContent.value = await marked(post.value.content); renderedContent.value = await marked(post.value.content);
} else {
router.push({ name: 'blog-overview' });
}
});
// Set SEO meta tags // Update SEO and structured data when post loads
watch(post, (newPost) => {
if (newPost) {
useSEO({ useSEO({
title: post.value.title, title: newPost.title,
description: post.value.description, description: newPost.description,
image: post.value.image, image: newPost.image,
url: `/blog/${slug}`, url: `/blog/${slug.value}`,
type: 'article', type: 'article',
author: post.value.author || 'nu11ed', author: newPost.author || 'nu11ed',
publishedTime: post.value.date, publishedTime: newPost.date,
keywords: post.value.keywords || 'sprite sheet, game development, blog' keywords: newPost.keywords || 'sprite sheet, game development, blog'
}); });
// Add structured data
addBlogPostSchema({ addBlogPostSchema({
title: post.value.title, title: newPost.title,
description: post.value.description, description: newPost.description,
author: post.value.author || 'nu11ed', author: newPost.author || 'nu11ed',
datePublished: post.value.date, datePublished: newPost.date,
image: post.value.image, image: newPost.image,
url: `/blog/${slug}` url: `/blog/${slug.value}`
}); });
// Add breadcrumb
addBreadcrumbSchema([ addBreadcrumbSchema([
{ name: 'Home', url: '/' }, { name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog' }, { name: 'Blog', url: '/blog' },
{ name: post.value.title, url: `/blog/${slug}` } { name: newPost.title, url: `/blog/${slug.value}` }
]); ]);
} else {
router.push({ name: 'blog-overview' });
} }
}); });
</script> </script>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted, watch } from 'vue';
import { useBlog, type BlogPost } from '../composables/useBlog'; import { useBlog, type BlogPost } from '../composables/useBlog';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
import { useStructuredData } from '../composables/useStructuredData'; import { useStructuredData } from '../composables/useStructuredData';
@@ -9,22 +9,30 @@
const { addBlogListSchema, addBreadcrumbSchema } = useStructuredData(); const { addBlogListSchema, addBreadcrumbSchema } = useStructuredData();
const posts = ref<BlogPost[]>([]); const posts = ref<BlogPost[]>([]);
// Set SEO meta tags synchronously
useSEO({
title: 'Blog - Latest Articles on Spritesheet Generation',
description: 'Explore our latest articles about sprite sheet generation, game development, pixel art, and sprite animation techniques.',
url: '/blog',
type: 'website',
keywords: 'sprite sheet blog, game development articles, pixel art tutorials, sprite animation'
});
// Add breadcrumb synchronously
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog' }
]);
onMounted(async () => { onMounted(async () => {
posts.value = await getPosts(); posts.value = await getPosts();
});
// Set SEO meta tags // Watch posts and add structured data when available
useSEO({ watch(posts, (newPosts) => {
title: 'Blog - Latest Articles on Spritesheet Generation', if (newPosts.length > 0) {
description: 'Explore our latest articles about sprite sheet generation, game development, pixel art, and sprite animation techniques.',
url: '/blog',
type: 'website',
keywords: 'sprite sheet blog, game development articles, pixel art tutorials, sprite animation'
});
// Add blog list structured data
if (posts.value.length > 0) {
addBlogListSchema( addBlogListSchema(
posts.value.map(post => ({ newPosts.map(post => ({
title: post.title, title: post.title,
description: post.description, description: post.description,
author: post.author || 'nu11ed', author: post.author || 'nu11ed',
@@ -34,13 +42,7 @@
})) }))
); );
} }
}, { immediate: true });
// Add breadcrumb
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog' }
]);
});
</script> </script>
<template> <template>

View File

@@ -1,24 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
import { useStructuredData } from '../composables/useStructuredData'; import { useStructuredData } from '../composables/useStructuredData';
const { addBreadcrumbSchema } = useStructuredData(); const { addBreadcrumbSchema } = useStructuredData();
onMounted(() => { // Set SEO synchronously
useSEO({ useSEO({
title: 'Contact Us - Get in Touch', title: 'Contact Us - Get in Touch',
description: 'Contact the Spritesheet Generator team. Join our Discord community or report bugs and contribute on Gitea. We\'d love to hear from you!', description: 'Contact the Spritesheet Generator team. Join our Discord community or report bugs and contribute on Gitea. We\'d love to hear from you!',
url: '/contact', url: '/contact',
type: 'website', type: 'website',
keywords: 'contact spritesheet generator, support, discord, gitea' keywords: 'contact spritesheet generator, support, discord, gitea'
});
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Contact', url: '/contact' }
]);
}); });
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Contact', url: '/contact' }
]);
</script> </script>
<template> <template>

View File

@@ -1,4 +1,3 @@
import { onMounted } from 'vue';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
import { useStructuredData } from '../composables/useStructuredData'; import { useStructuredData } from '../composables/useStructuredData';
import { useHead } from '@vueuse/head'; import { useHead } from '@vueuse/head';
@@ -6,60 +5,58 @@ import { useHead } from '@vueuse/head';
export function useHomeViewSEO() { export function useHomeViewSEO() {
const { addOrganizationSchema, addWebSiteSchema } = useStructuredData(); const { addOrganizationSchema, addWebSiteSchema } = useStructuredData();
onMounted(() => { // Set page SEO synchronously
// Set page SEO useSEO({
useSEO({ title: 'Spritesheet Generator - Create Game Spritesheets Online',
title: 'Spritesheet Generator - Create Game Spritesheets Online', description: 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.',
description: 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.', url: '/',
url: '/', type: 'website',
type: 'website', keywords: 'spritesheet generator, sprite sheet maker, game development, pixel art, sprite animation, game assets, 2D game tools'
keywords: 'spritesheet generator, sprite sheet maker, game development, pixel art, sprite animation, game assets, 2D game tools' });
});
// Add organization schema // Add organization schema
addOrganizationSchema(); addOrganizationSchema();
// Add website schema // Add website schema
addWebSiteSchema(); addWebSiteSchema();
// Add SoftwareApplication schema // Add SoftwareApplication schema
useHead({ useHead({
script: [ script: [
{ {
type: 'application/ld+json', type: 'application/ld+json',
children: JSON.stringify({ children: JSON.stringify({
'@context': 'https://schema.org', '@context': 'https://schema.org',
'@type': 'SoftwareApplication', '@type': 'SoftwareApplication',
'name': 'Spritesheet Generator', 'name': 'Spritesheet Generator',
'applicationCategory': 'DesignApplication', 'applicationCategory': 'DesignApplication',
'offers': { 'offers': {
'@type': 'Offer', '@type': 'Offer',
'price': '0', 'price': '0',
'priceCurrency': 'USD' 'priceCurrency': 'USD'
}, },
'operatingSystem': 'Web Browser', 'operatingSystem': 'Web Browser',
'description': 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.', 'description': 'Free online tool to create spritesheets for game development. Upload sprites, arrange them, and export as a spritesheet with animation preview.',
'url': 'https://spritesheetgenerator.online', 'url': 'https://spritesheetgenerator.online',
'screenshot': 'https://spritesheetgenerator.online/og-image.png', 'screenshot': 'https://spritesheetgenerator.online/og-image.png',
'featureList': [ 'featureList': [
'Free sprite editor', 'Free sprite editor',
'Automatic spritesheet generation', 'Automatic spritesheet generation',
'Customizable grid layouts', 'Customizable grid layouts',
'Animation preview', 'Animation preview',
'Cross-platform compatibility', 'Cross-platform compatibility',
'Zero installation required', 'Zero installation required',
'Batch processing', 'Batch processing',
'Multiple export formats (PNG, JPG, GIF, ZIP, JSON)' 'Multiple export formats (PNG, JPG, GIF, ZIP, JSON)'
], ],
'browserRequirements': 'Requires JavaScript. Requires HTML5.', 'browserRequirements': 'Requires JavaScript. Requires HTML5.',
'aggregateRating': { 'aggregateRating': {
'@type': 'AggregateRating', '@type': 'AggregateRating',
'ratingValue': '4.8', 'ratingValue': '4.8',
'ratingCount': '127' 'ratingCount': '127'
} }
}) })
} }
] ]
});
}); });
} }

View File

@@ -1,24 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue';
import { useSEO } from '../composables/useSEO'; import { useSEO } from '../composables/useSEO';
import { useStructuredData } from '../composables/useStructuredData'; import { useStructuredData } from '../composables/useStructuredData';
const { addBreadcrumbSchema } = useStructuredData(); const { addBreadcrumbSchema } = useStructuredData();
onMounted(() => { // Set SEO synchronously
useSEO({ useSEO({
title: 'Privacy Policy - Your Data Protection', title: 'Privacy Policy - Your Data Protection',
description: 'Read our privacy policy. Spritesheet Generator is a client-side tool that does not collect personal data or upload your images to our servers.', description: 'Read our privacy policy. Spritesheet Generator is a client-side tool that does not collect personal data or upload your images to our servers.',
url: '/privacy-policy', url: '/privacy-policy',
type: 'website', type: 'website',
keywords: 'privacy policy, data protection, client-side processing' keywords: 'privacy policy, data protection, client-side processing'
});
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Privacy Policy', url: '/privacy-policy' }
]);
}); });
addBreadcrumbSchema([
{ name: 'Home', url: '/' },
{ name: 'Privacy Policy', url: '/privacy-policy' }
]);
</script> </script>
<template> <template>