mdsycx

markdown with Sycamore

42
# mdsycx

## markdown with Sycamore

<Counter initial="42" />


About

Plain ol’ markdown is a bit boring… What if we could spice it up with Sycamore?

Meet mdsycx!

Installation

Just run the following command and you are all set to go.

cargo add mdsycx

Alternatively, you can manually add this line to your Cargo.toml file.

mdsycx = "0.1"

Usage

Using mdsycx in your Sycamore app is as easy as pie! Use the mdsycx::parse function to parse your markdown file and use the mdsycx::MDSycX component to render it using Sycamore.

let parsed = parse::<()>(markdown).unwrap();

view! { cx,
    div(class="markdown-container") {
        MDSycX(body=parsed.body)
    }
}

Markdown syntax

Use all your favorite features from markdown. mdsycx uses the excellent pulldown-cmark crate as a CommonMark spec-compliant parser.

Using components in your markdown

As advertised, it is possible to use Sycamore components directly in your markdown file.

To do so, you need to make sure the props implement the FromMd trait. Luckily, this can be derived automatically using the derive macro.

#[derive(Prop, FromMd)]
pub struct MyProps<'a, G: Html> {
    /// A prop that can be set from markdown.
    special_number: i32,
    /// The `children` prop is always required.
    children: Children<'a, G>,
}

Next, create a component with props of this type. Nothing special is going on here, just your regular Sycamore component.

#[component]
fn MyComponent<'a, G: Html>(cx: Scope<'a>, props: MyProps<'a, G>) -> View<G> {
    let children = props.children.call(cx);
    view! { cx,
        div {
            p { "Your special number is " (props.special_number) "!" }
            p { "Everything else:" }
            (children)
        }
    }
}

Last step is to provide this component to the MDSycX component. To do so, you need to create a ComponentMap. Basically, this tells mdsycx which component to use when it sees a component in markdown.

let components = ComponentMap::new()
    .with("MyComponent", MyComponent)
    .with(/* as many components as you like */);

view! { cx,
    div(class="markdown-container") {
        MDSycX(body=parsed.body, components=components)
    }
}

All that’s left is to use your fancy new component!

<MyComponent special_number="123">
    Hello from inside!
</MyComponent>

In fact, you can even replace built-in HTML elements such as <a> with your custom components! How cool is that?

let components = ComponentMap::new()
    .with("a", SpecialLink);

Note that all props are optional and will be set to their default value if they are missing in markdown.

Front matter

Your markdown file can contain a special section called the front matter. This is a place where you can specify metadata about your markdown file (such as the time it was written, or the author, etc…). The front matter should be surrounded by “---” characters at the top of your file and the data should be in YAML format.

You might have noticed that the mdsycx::parse function is actually generic. The generic parameter is the type of the front matter of the document. To access the data in the front-matter, you can use the .front_matter field on the struct returned from mdsycx::parse.

---
title: Writing markdown with mdsycx
author: Me
---

# Writing markdown with mdsycx

Yada yada...

Parsing markdown at compile-time

TODO: This part hasn’t been written yet.

Server Side Rendering (SSR)

Sycamore’s Server Side Rendering support should work out of the box! Just make sure you are rendering the same thing on both the server and the client!

let string = sycamore::render_to_string(App);

Roadmap

Many features are not yet implemented. Here are a few: