[FEAT] Fix vue warn
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user