2

What I'm trying to do

A simple way to render the content of a markdown file when it's passed as a string to another component using .compiledContent (or even using .rawContnent)? Or even a better way than this as obviously usually in Astro we can use the <Content /> Component, but from my knowledge, I can't pass a component or this functionality to another component without using a <slot /> in the parent component.

I have some JS for the parent component and using a <slot/> instead of passing the props to the component would change things, so hopefully looking for a solution with using this.

My setup

  • Data stored in /src/data/experience as markdown files with a year and a description formatted as markdown in the content section of each file
  • A component called Tabs.astro which takes props of headings and contents which are both lists of strings
  • A page /src/pages/experience.astro with the Tabs component in it which is displaying this data

I take the below code to get the data from the markdown files and pass the years and descriptions to the Tab component.

experience.astro

---
import Tabs from "../components/Tabs.astro";

const jobs = await Astro.glob("../data/experience/*.md");
const years = jobs.map((job) => job.frontmatter.year);
const descriptions = jobs.map((job) => job.compiledContent);
---
<!-- My component taking the data to be rendered -->
<Tabs headings={years} contents={descriptions} />

Tabs.astro

And the component renders the info like so

<!-- Tabs -->
<div class="tabs">
  <ul class="tabs-header">
    {
      headings.map((heading) => (
        <li>{heading}</li>
      ))
    }
  </ul>
  <ul class="tabs-content">
    {contents.map((content) => <li class="tab">{content}</li>)}
  </ul>
</div>

My current solution

At the moment using .compiledContent gets me the correct HTML, however it is all in a string so the HTML doesn't actually render.

What I'm looking for

  • Is there a native way in Astro to pass markdown as a prop to a component?
  • If not is there a manual and recommended way in Astro to convert a markdown string and sanitise it to protect against XSS attacks? (if this is a risk in Astro when rendered statically?)
  • If not what are your most recommended ways to render markdown and sanitise it in JS?

Thanks so much for your time and help! I'm loving using Astro

p.s Also happy to concede and just use a <slot/> in my component if needed... ;)

Lushawn
  • 522
  • 1
  • 3
  • 17

2 Answers2

4

Astro has a set:html directive you can use in combination with a Fragment like this

<Fragment set:html={post.compiledContent()}/>
Bryce Russell
  • 647
  • 3
  • 8
  • Hey thanks for the input, I have tested this and it does work - but are you aware if I need to santise the content to protect against XSS with this method? Thanks :) – Lushawn Dec 20 '22 at 17:11
  • 2
    I replied to your [discord](https://astro.build/chat) thread since its easier to communicate there, but in this case no. The only time you have to sanitize is if its data created by user input like this comment – Bryce Russell Dec 20 '22 at 18:16
2

After a bit of struggling with this myself, the current solution from the Astro docs for a single file without looping is the following. Import your file with {Content as YourAliasName} from '../yourPath/yourFileName.md' Then just use it as a tag <YourAliasName />

Example from the docs for reference:

---
import {Content as PromoBanner} from '../components/promoBanner.md';
---

<PromoBanner />

https://docs.astro.build/en/guides/markdown-content/#the-content-component

kirbby
  • 226
  • 3
  • 8