vertigo-cmark 0.1.4

Allows to render CommonMark inside Vertigo tree
Documentation

vertigo-cmark

Converts CommonMark string into rendered vertigo DomElement.

crates.io Documentation MIT or Apache 2.0 licensed Dependency Status CI downloads

See Changelog for recent features.

Example

Dependencies:

vertigo = "0.14"
vertigo-cmark = "0.1"
use vertigo::{DomNode, dom, main};

const CONTENT: &str = r#"
# Hello world

## Paragraph

Lorem ipsum dolor sit amet, __consectetur__ adipiscing elit, sed do
```eiusmod tempor incididunt```
ut *labore* et dolore magna aliqua.

## List

* Lorem ipsum
* dolor sit amet
* consectetur adipiscing elit

## Table

| Lorem           | Ipsum          |
| --------------- | -------------- |
| dolor sit amet  | consectetur    |
| adipiscing elit | sed do eiusmod |
"#;

#[main]
fn app() -> DomNode {
    let content = vertigo_cmark::to_vertigo(CONTENT);
    dom! {
        <html>
            <head/>
            <body>{ content }</body>
        </html>
    }
}

image

Features

  • Regular, bod, italic, strike-through text
  • Headings
  • Paragraphs
  • Tables
  • Blockquotes
  • Codeblocks
  • Code highlighting (with syntect feature)
  • Lists (numbers, bullets)
  • Rules
  • Task list markers
  • Footnotes
  • Soft/hard breaks
  • Links
  • Images
  • Html (with html feature), sanitized by default

Security

Markdown can carry raw HTML and links to any address, and vertigo-cmark builds DOM from them directly — there is no HTML string to clean afterwards. So by default everything goes through SafeHtml: elements and attributes from ammonia's default whitelist and links and images only with safe schemes. Scripts, styles, event handlers, frames, forms and javascript: addresses don't get into the page, so rendering text from users is safe.

For content you control, TrustedHtml renders everything as written. Anything in between is an own HtmlPolicy — usually delegating to SafeHtml all but a few elements:

use std::borrow::Cow;
use vertigo_cmark::{
    CMarkStyle, ElementAction, HtmlPolicy, SafeHtml, events_to_vertigo,
    pulldown_cmark::Parser,
};

/// Safe HTML plus YouTube players.
struct WithVideos;

impl HtmlPolicy for WithVideos {
    fn element(&self, name: &str) -> ElementAction {
        match name {
            "iframe" => ElementAction::Keep,
            name => SafeHtml.element(name),
        }
    }

    fn attribute<'v>(
        &self,
        element: &str,
        name: &str,
        value: &'v str,
    ) -> Option<Cow<'v, str>> {
        match (element, name) {
            ("iframe", "src") => value
                .starts_with("https://www.youtube.com/embed/")
                .then_some(Cow::Borrowed(value)),
            _ => SafeHtml.attribute(element, name, value),
        }
    }

    fn destination<'u>(
        &self,
        url: &'u str,
        image: bool,
    ) -> Option<Cow<'u, str>> {
        SafeHtml.destination(url, image)
    }
}

let content = events_to_vertigo(
    Parser::new(CONTENT),
    CMarkStyle::default(),
    &WithVideos,
);