Packages
mdex
0.2.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.5
retired
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Fast and extensible Markdown for Elixir
Current section
Files
Jump to
Current section
Files
native/comrak_nif/src/lib.rs
#![allow(dead_code)]
#![allow(unused_variables)]
#[macro_use]
extern crate rustler;
mod decoder;
mod encoder;
mod inkjet_adapter;
mod types;
use comrak::{markdown_to_html_with_plugins, Arena, ComrakPlugins, Options};
use decoder::ex_node_to_comrak_ast;
use encoder::to_elixir_ast;
use inkjet_adapter::InkjetAdapter;
use rustler::{Decoder, Encoder, Env, NifResult, Term};
use types::{atoms::ok, options::*};
rustler::init!(
"Elixir.MDEx.Native",
[
parse_document,
markdown_to_html,
markdown_to_html_with_options,
ast_to_html,
ast_to_html_with_options,
ast_to_commonmark,
ast_to_commonmark_with_options
]
);
#[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html<'a>(env: Env<'a>, md: &str) -> NifResult<Term<'a>> {
let inkjet_adapter = InkjetAdapter::default();
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let html = markdown_to_html_with_plugins(md, &Options::default(), &plugins);
Ok((ok(), html).encode(env))
}
#[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html_with_options<'a>(
env: Env<'a>,
md: &str,
options: ExOptions,
) -> NifResult<Term<'a>> {
let comrak_options = comrak::Options {
extension: extension_options_from_ex_options(&options),
parse: parse_options_from_ex_options(&options),
render: render_options_from_ex_options(&options),
};
match &options.features.syntax_highlight_theme {
Some(theme) => {
let inkjet_adapter = InkjetAdapter::new(
theme,
options
.features
.syntax_highlight_inline_style
.unwrap_or(true),
);
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let unsafe_html = markdown_to_html_with_plugins(md, &comrak_options, &plugins);
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
None => {
let unsafe_html = comrak::markdown_to_html(md, &comrak_options);
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
}
}
#[rustler::nif(schedule = "DirtyCpu")]
fn parse_document<'a>(env: Env<'a>, md: &str, options: ExOptions) -> NifResult<Term<'a>> {
let comrak_options = comrak::Options {
extension: extension_options_from_ex_options(&options),
parse: parse_options_from_ex_options(&options),
render: render_options_from_ex_options(&options),
};
let arena = Arena::new();
let root = comrak::parse_document(&arena, md, &comrak_options);
let ex_ast = to_elixir_ast(root);
Ok((ok(), vec![ex_ast]).encode(env))
}
#[rustler::nif(schedule = "DirtyCpu")]
fn ast_to_html<'a>(env: Env<'a>, ast: Term<'a>) -> NifResult<Term<'a>> {
let ex_node = types::nodes::ExNode::decode(ast)?;
let arena = Arena::new();
let comrak_ast = ex_node_to_comrak_ast(&arena, &ex_node);
// FIXME: error handling format_html and from_utf8
let inkjet_adapter = InkjetAdapter::default();
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let mut buffer = vec![];
comrak::format_html_with_plugins(comrak_ast, &Options::default(), &mut buffer, &plugins)
.unwrap();
let html = String::from_utf8(buffer).unwrap();
Ok((ok(), html).encode(env))
}
#[rustler::nif(schedule = "DirtyCpu")]
fn ast_to_html_with_options<'a>(
env: Env<'a>,
ast: Term<'a>,
options: ExOptions,
) -> NifResult<Term<'a>> {
let ex_node = types::nodes::ExNode::decode(ast)?;
let arena = Arena::new();
let comrak_ast = ex_node_to_comrak_ast(&arena, &ex_node);
let comrak_options = comrak::Options {
extension: extension_options_from_ex_options(&options),
parse: parse_options_from_ex_options(&options),
render: render_options_from_ex_options(&options),
};
match &options.features.syntax_highlight_theme {
Some(theme) => {
let inkjet_adapter = InkjetAdapter::new(
theme,
options
.features
.syntax_highlight_inline_style
.unwrap_or(true),
);
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let mut buffer = vec![];
comrak::format_html_with_plugins(comrak_ast, &comrak_options, &mut buffer, &plugins)
.unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
None => {
let mut buffer = vec![];
comrak::format_html(comrak_ast, &comrak_options, &mut buffer).unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
}
}
#[rustler::nif(schedule = "DirtyCpu")]
fn ast_to_commonmark<'a>(env: Env<'a>, ast: Term<'a>) -> NifResult<Term<'a>> {
let ex_node = types::nodes::ExNode::decode(ast)?;
let arena = Arena::new();
let comrak_ast = ex_node_to_comrak_ast(&arena, &ex_node);
// FIXME: error handling format_html and from_utf8
let inkjet_adapter = InkjetAdapter::default();
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let mut buffer = vec![];
comrak::format_commonmark_with_plugins(comrak_ast, &Options::default(), &mut buffer, &plugins)
.unwrap();
let html = String::from_utf8(buffer).unwrap();
Ok((ok(), html).encode(env))
}
#[rustler::nif(schedule = "DirtyCpu")]
fn ast_to_commonmark_with_options<'a>(
env: Env<'a>,
ast: Term<'a>,
options: ExOptions,
) -> NifResult<Term<'a>> {
let ex_node = types::nodes::ExNode::decode(ast)?;
let arena = Arena::new();
let comrak_ast = ex_node_to_comrak_ast(&arena, &ex_node);
let comrak_options = comrak::Options {
extension: extension_options_from_ex_options(&options),
parse: parse_options_from_ex_options(&options),
render: render_options_from_ex_options(&options),
};
match &options.features.syntax_highlight_theme {
Some(theme) => {
let inkjet_adapter = InkjetAdapter::new(
theme,
options
.features
.syntax_highlight_inline_style
.unwrap_or(true),
);
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let mut buffer = vec![];
comrak::format_commonmark_with_plugins(
comrak_ast,
&comrak_options,
&mut buffer,
&plugins,
)
.unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
None => {
let mut buffer = vec![];
comrak::format_commonmark(comrak_ast, &comrak_options, &mut buffer).unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
maybe_sanitize(env, unsafe_html, options.features.sanitize)
}
}
}
fn maybe_sanitize(env: Env, unsafe_html: String, sanitize: bool) -> NifResult<Term> {
let html = match sanitize {
true => ammonia::clean(&unsafe_html),
false => unsafe_html,
};
Ok((ok(), html).encode(env))
}