add: extract plain faq

Add Schema Org for FAQ
This commit is contained in:
webfussel 2025-06-11 08:54:32 +02:00
parent bb77bb6a5b
commit a86b89dc98
5 changed files with 40 additions and 12 deletions

View file

@ -129,5 +129,21 @@ const oneOff : Service[] = [
}, },
] ]
const faq = await queryCollection('faq').path('/snippets/faq/booking').first() const { data: faq } = await useAsyncData('faq', () => queryCollection('faq').path('/snippets/faq/booking').first())
const texts = usePlainFaq(faq.value?.body.value)
if (faq) {
useSchemaOrg({
'@context': 'https://schema.org',
'@type': 'FAQPage',
'mainEntity': texts.map(entity => ({
'@type': 'Question',
'name': entity.question,
'acceptedAnswer': {
'@type': 'Answer',
'text': entity.answer,
},
}))
})
}
</script> </script>

View file

@ -10,9 +10,10 @@
<script setup lang="ts"> <script setup lang="ts">
type Props = { type Props = {
title: string title: string
answer ?: string
} }
defineProps<Props>() const { title, answer = '' } = defineProps<Props>()
const open = ref(false) const open = ref(false)
const toggle = (event : MouseEvent) => { const toggle = (event : MouseEvent) => {

20
app/composables/faq.ts Normal file
View file

@ -0,0 +1,20 @@
import type { MinimalElement, MinimalNode } from '@nuxt/content'
const extractText = (element ?: MinimalNode) : string => {
if (!element) return ''
if (typeof element === 'string') return element
const [,, ...nodes] = element
return nodes?.map((el : MinimalNode) => typeof el === 'string' ? el : extractText(el)).join(' ') ?? ''
}
export const usePlainFaq = (body ?: MinimalNode[]) => {
if (!body) return []
return body.map(part => {
const [, meta] = part as MinimalElement
return {
question: meta.title,
answer: extractText(part).replace(/\n/g, ' ')
}
})
}

View file

@ -10,21 +10,13 @@ export default defineContentConfig({
skills: defineCollection({ skills: defineCollection({
type: 'page', type: 'page',
source: 'snippets/skills/*.md', source: 'snippets/skills/*.md',
schema: z.object({
title: z.string(),
img: z.object({
path: z.string(),
name: z.string(),
position: z.string(),
}),
})
}), }),
faq: defineCollection({ faq: defineCollection({
type: 'page', type: 'page',
source: 'snippets/faq/*.md', source: 'snippets/faq/*.md',
schema: z.object({ schema: z.object({
title: z.string(), rawbody: z.string(),
}) })
}) })
} }

1
package-lock.json generated
View file

@ -3723,7 +3723,6 @@
}, },
"node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": { "node_modules/@parcel/watcher-wasm/node_modules/napi-wasm": {
"version": "1.1.0", "version": "1.1.0",
"dev": true,
"inBundle": true, "inBundle": true,
"license": "MIT" "license": "MIT"
}, },