Skip to content

Commit e184ea2

Browse files
authored
feat(app): add PageHeaderLinks component (#235)
1 parent 800392d commit e184ea2

File tree

3 files changed

+122
-2
lines changed

3 files changed

+122
-2
lines changed

app/components/PageHeaderLinks.vue

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<script setup lang="ts">
2+
import { useClipboard } from '@vueuse/core'
3+
4+
const route = useRoute()
5+
const toast = useToast()
6+
const { copy, copied } = useClipboard()
7+
const site = useSiteConfig()
8+
const isCopying = ref(false)
9+
console.log(site)
10+
11+
const mdPath = computed(() => `${site.url}/raw${route.path}.md`)
12+
13+
const items = [
14+
{
15+
label: 'Copy Markdown link',
16+
icon: 'i-lucide-link',
17+
onSelect() {
18+
copy(mdPath.value)
19+
toast.add({
20+
title: 'Copied to clipboard',
21+
icon: 'i-lucide-check-circle'
22+
})
23+
}
24+
},
25+
{
26+
label: 'View as Markdown',
27+
icon: 'i-simple-icons:markdown',
28+
target: '_blank',
29+
to: `/raw${route.path}.md`
30+
},
31+
{
32+
label: 'Open in ChatGPT',
33+
icon: 'i-simple-icons:openai',
34+
target: '_blank',
35+
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
36+
},
37+
{
38+
label: 'Open in Claude',
39+
icon: 'i-simple-icons:anthropic',
40+
target: '_blank',
41+
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
42+
}
43+
]
44+
45+
async function copyPage() {
46+
isCopying.value = true
47+
copy(await $fetch<string>(`/raw${route.path}.md`))
48+
isCopying.value = false
49+
}
50+
</script>
51+
52+
<template>
53+
<UButtonGroup>
54+
<UButton
55+
label="Copy page"
56+
:icon="copied ? 'i-lucide-copy-check' : 'i-lucide-copy'"
57+
color="neutral"
58+
variant="outline"
59+
:loading="isCopying"
60+
:ui="{
61+
leadingIcon: [copied ? 'text-primary' : 'text-neutral', 'size-3.5']
62+
}"
63+
@click="copyPage"
64+
/>
65+
<UDropdownMenu
66+
:items="items"
67+
:content="{
68+
align: 'end',
69+
side: 'bottom',
70+
sideOffset: 8
71+
}"
72+
:ui="{
73+
content: 'w-48'
74+
}"
75+
>
76+
<UButton
77+
icon="i-lucide-chevron-down"
78+
size="sm"
79+
color="neutral"
80+
variant="outline"
81+
/>
82+
</UDropdownMenu>
83+
</UButtonGroup>
84+
</template>

app/pages/[...slug].vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,18 @@ const links = computed(() => {
5757
<UPageHeader
5858
:title="page.title"
5959
:description="page.description"
60-
:links="page.links"
6160
:headline="headline"
62-
/>
61+
>
62+
<template #links>
63+
<UButton
64+
v-for="(link, index) in page.links"
65+
:key="index"
66+
v-bind="link"
67+
/>
68+
69+
<PageHeaderLinks />
70+
</template>
71+
</UPageHeader>
6372

6473
<UPageBody>
6574
<ContentRenderer
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { withLeadingSlash } from 'ufo'
2+
import { stringify } from 'minimark/stringify'
3+
import { queryCollection } from '@nuxt/content/nitro'
4+
import type { Collections } from '@nuxt/content'
5+
6+
export default eventHandler(async (event) => {
7+
const slug = getRouterParams(event)['slug.md']
8+
if (!slug?.endsWith('.md')) {
9+
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
10+
}
11+
12+
const path = withLeadingSlash(slug.replace('.md', ''))
13+
14+
const page = await queryCollection(event, 'docs' as keyof Collections).path(path).first()
15+
if (!page) {
16+
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
17+
}
18+
19+
// Add title and description to the top of the page if missing
20+
if (page.body.value[0]?.[0] !== 'h1') {
21+
page.body.value.unshift(['blockquote', {}, page.description])
22+
page.body.value.unshift(['h1', {}, page.title])
23+
}
24+
25+
setHeader(event, 'Content-Type', 'text/markdown; charset=utf-8')
26+
return stringify({ ...page.body, type: 'minimark' }, { format: 'markdown/html' })
27+
})

0 commit comments

Comments
 (0)