Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to render remote markdown using content layer API #9543

Open
johnmw opened this issue Oct 3, 2024 · 3 comments
Open

How to render remote markdown using content layer API #9543

johnmw opened this issue Oct 3, 2024 · 3 comments
Labels
5.0 For 5.0 stable release add new content Document something that is not in docs. May require testing, confirmation, or affect other pages.

Comments

@johnmw
Copy link

johnmw commented Oct 3, 2024

📚 Subject area/topic

markdown, content layer api

📋 Suggested page

https://docs.astro.build/en/reference/configuration-reference/#experimentalcontentlayer

📋 General description or bullet points (if proposing new content)

I think that with the new content layer API, rendering remote markdown (from a server or api) is going to be a common use case.

The Astro docs currently says "Astro does not include built-in support for remote Markdown outside of experimental content collections!"

However I was unable to find any further information or examples about rendering remote (server) markdown.

So firstly, I was wondering if there already is an good example that I have missed?

If not, I have got some rough code (shown below) that renders markdown using Astros built in functions that seems to work and might help someone. But I would really like someone to review it and let me know things that can be improved.

Example Loader that renders remote markdown:

import { defineCollection, z } from 'astro:content';
import type { Loader } from "astro/loaders";

function markdownTestLoader({}):Loader {
  return {
    name: "markdown-test-loader",
    load: async ({ config, store, parseData, generateDigest, entryTypes }) => {
      
      store.clear();
      
      // Would normally load this JSON data from API. 
      // The "content" field has the markdown I want to render
      const dummyAPIData = {
        id: "home",
        title: "Test Markdown Data",
        content: "## Markdown to Render \nTesting markdown rendering.\n- List item 1\n- List item 2"
      }
      
      const id = dummyAPIData.id;
      const data = await parseData({ id, data:dummyAPIData });
      const body = dummyAPIData.content; // markdown to render next
      const digest = generateDigest(data);

      // Render markdown to HTML using built in Astro markdown render function
      let rendered;
      const markdownEntryType = entryTypes.get(".md");
      if( markdownEntryType?.getRenderFunction ) {
        const render = await markdownEntryType.getRenderFunction(config);
        rendered = await render?.({
          id,
          data,
          body,
          digest
        });
      }

      store.set({ id, data, rendered, digest });
    }
  }
}

// Define collection with loader

const markdownTestCollection = defineCollection({
  loader: markdownTestLoader({}),
  schema: z.object({
    id: z.string(),
    title: z.string(),
    content: z.string()
  })
});

export const collections = {
  'markdownTestCollection': markdownTestCollection  
};

The markdown HTML can be displayed on the page using the "render" function and built in "Content" component:

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

export async function getStaticPaths() {
  const pages = await getCollection("markdownTestCollection");
  return pages.map((page) => ({    
    params: { 
      slug: page.id },
    props: { 
      page 
    },
  }));
}

const { page } = Astro.props;
const { Content, headings } = await render(page);
---
<h1>{page.data.title}</h1>
<Content />

As I said, I'm sure there are things above that could be done better.

🖥️ Reproduction of code samples in StackBlitz

No response

@johnmw johnmw added the add new content Document something that is not in docs. May require testing, confirmation, or affect other pages. label Oct 3, 2024
@Fryuni
Copy link
Member

Fryuni commented Oct 3, 2024

We don't add guides and recipes for experimental APIs, only the refence and examples in the description there. So it won't be added on the docs for v4.

The feature is stabilized on v5, so we can document it there. The docs for the LoaderContext is missing the entryTypes property which enables rendering the different content types. We can add documentation for that and how to use it on the guide for writing a loader.

@Fryuni Fryuni added the 5.0 For 5.0 stable release label Oct 3, 2024
@sarah11918
Copy link
Member

Thanks for this @johnmw ! Just showing off working code is already very helpful to others, and I appreciate your care in wanting to further make sure that the code is something recommended for others to copy.

Fryuni is right that any docs for this would have to go on our v5 beta docs. I will also ask @ascorbic to take a look to ensure that we end up with something that we'd recommend as a "happy path" as a general model!

If so, then I also agree this is for the Loader API page, in one of two ways:

  • an example of a loader that fetches remote Markdown (the first code snippet only. I think the other code examples are pretty standard usage once you have the loader configured properly? There's nothing there that seems unique to having built that particular loader?)

or

  • a link from this page to a full recipe set of instructions that includes everything above, but uses a real data fetch from a real API. This should be something that someone can follow along and have something working in their project at the end.

@ascorbic
Copy link
Contributor

ascorbic commented Oct 3, 2024

I agree! Adding it to the Loader API page would work best.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
5.0 For 5.0 stable release add new content Document something that is not in docs. May require testing, confirmation, or affect other pages.
Projects
None yet
Development

No branches or pull requests

4 participants