Accessing markdown frontmatter attributes inside the head
Opened this issue · 6 comments
Can you advise on how you would be able to get the frontmatter data inside the head element?
export default {
asyncData({ app }) {
return {
aboutPage: app.$markdown.about
};
},
data() {
return {
aboutPageContent: null
};
},
created() {
this.aboutPageContent = () => this.$markdown.loadContent();
},
head() {
return {
title: <access data here>
};
}
};
So this might link into why I asked about single pages.
Doing the above I can't access all properties.
So with the above script section this works <h2>{{ aboutPage.title }}</h2>
but this doesn't <cover :thumbnail="aboutPage.hero" />
If I look in the generate nuxt payload I can see that hero is in there but I can't seem to access it using aboutPage.hero
{aboutPage:{title:"About",hero:"about\u002Fcarl-newton-1JcEl81di6Y-unsplash.jpg",file:a,path:b,collection:a}}
However...
If I do this (using the same structure for the blog _slug
and not the blog index
)
export default {
asyncData({ app }) {
return {
aboutPage: app.$markdown.loadData()
};
},
data() {
return {
aboutPageContent: null
};
},
created() {
this.aboutPageContent = () => this.$markdown.loadContent();
},
head() {
return {
title: this.aboutPage.title
};
}
};
I can set the title inside the head and my hero now becomes available via blogPage.hero
So maybe this is the reason to add in a single page type collection? So that we can use aboutPage: app.$markdown.page
instead of aboutPage: app.$markdown.loadData()
for single pages?
So this works
asyncData({ app, $dayjs }) {
const blogPost = app.$markdown.loadData();
blogPost.date = $dayjs(blogPost.date).format("YYYY");
return {
blogPost
};
},
but this doesn't
asyncData({ app, $dayjs }) {
const blogPosts = app.$markdown.blog
blogPosts.date = $dayjs(blogPosts.date).format("YYYY");
return {
blogPosts
};
}
So there's something about the named collection that doesn't seem to allow access to the data. So in the first example that just uses loadData()
- I can do this blogPost.date = 'test'
and now all my dates say test
as expected, but in that second example that uses the named collection I can't transform any of the data meaning blogPost.date = 'test'
doesn't work.
You can access the front matter for the current page using loadData()
in asyncData
and accessing the data you want in head
.
<script>
export default {
asyncData ({ app }) {
return {
blogPost: app.$markdown.loadData()
}
},
head () {
return {
title: this.blogPost.title
}
}
}
</script>
Is there a reason you don't want to use loadData
?
Regarding your example which didn't work, this is because blogPosts
is an array. Therefore, you are attempting to set the date
property of an array.
asyncData({ app, $dayjs }) { const blogPosts = app.$markdown.blog blogPosts.date = $dayjs(blogPosts.date).format("YYYY"); return { blogPosts }; }
You may want to do something like this instead:
asyncData({ app, $dayjs }) {
const blogPosts = app.$markdown.blog
blogPosts.forEach((blogPost) => {
blogPost.date = $dayjs(blogPost.date).format("YYYY")
})
return {
blogPosts
}
}
Ok, cool. The date thing was obviously me being stupid I should have clocked the array output.
So with regards to app.$markdown.loadData()
I have this folder structure
content
- blog
- - posts
- - - post1.md
- - - etc...
- - index.md
pages
- blog
- - posts
- - - _slug.vue
- - tags
- - - _slug.vue
- - index.vue
I have this script in blog/index.vue
asyncData({ app, $dayjs }) {
const blogContent = app.$markdown.loadData()
const blogPosts = app.$markdown.blogposts;
blogPosts.forEach(blogPost => {
blogPost.date = $dayjs(blogPost.date).format("YYYY");
});
return {
blogContent,
blogPosts
};
},
And this settings in nuxt
{
name: 'blogposts',
directory: 'content/blog/posts',
includeSubdirectories: false,
routePrefix: '/blog/post/',
serverTransform(collection) {
collection.forEach(({ content, data }) => {
data.mins = Math.round(content.split(' ').length / 250) || 1
data.tags = data.tags.map((tag) => {
const slug = tag.toLowerCase();
return {
name: slug,
path: `/blog/tag/${slug}/`
}
})
})
return collection.sort((a, b) => b.data.date - a.data.date)
},
clientTransform() {
return function (collection) {
collection.forEach((data) => {
data.date = new Date(data.date)
})
return collection
}
}
}
So I'm pretty much following your example.
When I generate I get this error Error generating route "/blog/": This page could not be found
. This is coming from the fact I have an index.md
inside the blog folder because if I remove it I don't get the error but I know have no control over the content for the blog list page, only the posts output. If I add the route manually into router I still get the error, I can also see in one of your examples you provide a mock promise, and I don't want to do anything like that, it feels like a hack (also I still get the same error).
So, if I add this to nuxt config
{
name: 'blogcontent',
directory: 'content/blog',
includeSubdirectories: false,
routePrefix: '/blog/'
}
I know get no errors, but as you've pointed out already the output of the new blogcontent is now an array - so doing const blogContent = app.$markdown.blogcontent
and {{ blogContent.title }}
doesn't work because it's an array output.
If i were to leave in the new blogcontent
definition in your plugin config and change to const blogContent = app.$markdown.loadData()
then it works as expected but I've had to define the route in your plugin config with a named collection that I'm not even using.
Does that all make sense? I have no problem using loadData as it works for the about page great, but because of the routing error with blog, and the way I have had to get around it, maybe something could be done to make it more intuitive.
Okay I see what you mean: the problem is that you have to specify a collection for your blogContent
, even though it's just a single page and you won't use the named collection anywhere.
Currently, you have to specify all the directories where your Markdown files are, otherwise, Nuxt Markdown doesn't know about them; however, maybe it's worth Nuxt Markdown automatically finding all of the Markdown files in the content
directory and only use collections where you need e.g. for a collection of blog posts or projects. I'll have a think about it, as that would be a pretty major change to how Nuxt Markdown works.
Yeah maybe this just comes back to single page handling /shrug haha