#Generating frontmatter based on markdown

1 messages · Page 1 of 1 (latest)

sinful solar
#

Hi! Is it possible to automatically update frontmatter (in my case, extracting h1 from md to 'title' frontmatter field) in collection? Ideally this should not break zod typings and place updated/generated values into regular frontmatter, not remarkPluginFrontmatter.

spiral python
#

Hi! I'm not aware of an easy way to do this, but I guess it might be doable using a custom remark plugin by looking for your h1 and injecting its content in the frontmatter? If you're not defining a title in the frontmatter you might need to add .default("") in your schema to avoid errors though.

But if you're willing to switch from .md to .mdx, you could easily done that but the other way around: by defining your title in the frontmatter and using ${frontmatter.title} in your MDX file.

sinful solar
#

i've alredy tried with remark plugin, and it is not ideal. Shutting up zod is bearable, but updated frontmatter goes into remarkPluginFrontmatter. And as far as i understood, plugin is executed only on render, so it is impossible to use collection to form something like list of posts easily based on frontmatter contents.

But if you're willing to switch from .md to .mdx, you could easily done that but the other way around: by defining your title in the frontmatter and using ${frontmatter.title} in your MDX file.
Initially i did layout with <h1> + <Content/>, so less typing in each content file :)

Ok, so if there are no easy way, i'll feel less bad about over engineering stuff around.

#

And just in case this post is XY problem, that's what i want: page with list of posts and posts pages from collection. Don't want to type same things twice, so somehow need to get title out of content file to fill title in list + fill meta tags in page header. Additionally, might as well generate post description based on first paragraph, and put created/updated dates from git. Docs about using remark plugin shows how to add reading time, and this is fine, but as we discussed earlier, works well only inside post, and not really good to form something like list of posts

spiral python
#

but updated frontmatter goes into remarkPluginFrontmatter

Oh right, I forgot about that sorry. But, is this really an issue?

Another solution would be to define the h1 in the frontmatter, and starts your content without including it. Then you use entry.data.title as h1 in your template right before the content?

generate post description based on first paragraph

Hmm, for that I think you would need a remark plugin unfortunately. Either a custom one or an existing one like https://www.npmjs.com/package/@eligundry/remark-excerpt (I have not tested it).

put created/updated dates from git

Same, I don't think you can do that outside a remark plugin.

not really good to form something like list of posts

I'm not sure I understand the issue here. If you are using Content collections, your posts index could look like:

---
import { getCollection, render } from "astro:content";

const posts = await getCollection("blog");
const postsWithRemarkFrontmatter = await Promise.all(posts.map(async (post) => {
  const { remarkPluginFrontmatter } = await render(entry);
  return { ...post, remarkPluginFrontmatter }
}));
---
<ul>
  {postsWithRemarkFrontmatter.map((post) => {
    return (<li><a href={post.id}>{post.data.title}</a></li>)
  })
  {/* You have access to the frontmatter through `data` and you should be able to use `post.remarkPluginFrontmatter` too now. */}
</ul>

Oh do you mean because you need to call render? Well, I think this is a good trade off to avoid engeneering a more complex approach.

sinful solar
#

is this really an issue?
not really, just dealing with additional cases ;)

Then you use entry.data.title as h1 in your template right before the content?
yes, this is how i currently do this

remark plugin unfortunately
plugin itself is not a problem, i think i got how to write them

you need to call render? Well, I think this is a good trade off to avoid engeneering a more complex approach
Yeah, i was looking for a way to avoid rendering whole collection to grab a couple of strings from each file. If this is the "astro way" to do this, then ok

sinful solar
#

In the end, did the thing with rendering the whole collection. Also I merged remarkPluginFrontmatter into post.data both in post list and post page.
And as side note, getting dates from git looks impossible with remark plugins, since they don't get filenames

spiral python
#

Did you try https://docs.astro.build/en/recipes/modified-time/ ? Last time I checked I think it was working but it was a long time ago...

But as noted in the recipe:

Your host may be performing shallow clones which do not retrieve the full git history.
This means that depending on your build environment you might not get the dates... I'm not aware of an alternative rather than updating a date manually in the frontmatter.

Which even if it seems restrictive might be better according to the usage you want for them? I mean, if you have an RSS feed, maybe this is okay for the post to not be defined as updated when you fix a typo or swap a link and this should only be defined as updated for more important changes? So, yes sorry, not ideal but I don't have other ideas to deal with this.

Docs

Build a remark plugin to add the last modified time to your Markdown and MDX.

sinful solar
#

Thanks for some new ideas. I believe i've read through this link at some point, but forgot about it. Main takeaway that it is possible to get filepath in vfile. Right now i've bypassed it with getting filename in astro's template through filePath field in the collections's item.

About shallow clone repo. This is not a problem since I'm building/hosting myself.

As for manual dates, i'm not sure about all this. I still want to try to automate the process and decide afterwards if it really is better.