Skip to content

Commit

Permalink
expose safe_html
Browse files Browse the repository at this point in the history
  • Loading branch information
leandrocp committed Jan 9, 2025
1 parent 155d7ee commit c18126d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
5 changes: 5 additions & 0 deletions lib/mdex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -602,4 +602,9 @@ defmodule MDEx do

defp maybe_trim({:ok, result}), do: {:ok, String.trim(result)}
defp maybe_trim(error), do: error

# TODO: spec/docs
def safe_html(unsafe_html, sanitize, escape_tags, escape_curly_braces_in_code) do
Native.safe_html(unsafe_html, sanitize, escape_tags, escape_curly_braces_in_code)
end
end
2 changes: 2 additions & 0 deletions lib/mdex/native.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ defmodule MDEx.Native do
mode: mode,
force_build: System.get_env("MDEX_BUILD") in ["1", "true"]

def safe_html(_unsafe_html, _sanitize, _escape_tags, _escape_curly_braces_in_code), do: :erlang.nif_error(:nif_not_loaded)

# markdown
# - to document (parse)
# - to html
Expand Down
32 changes: 25 additions & 7 deletions native/comrak_nif/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use types::{atoms::ok, document::*, options::*};
rustler::init!(
"Elixir.MDEx.Native",
[
safe_html,
parse_document,
markdown_to_html,
markdown_to_html_with_options,
Expand Down Expand Up @@ -50,7 +51,7 @@ fn markdown_to_html<'a>(env: Env<'a>, md: &str) -> NifResult<Term<'a>> {
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let unsafe_html = comrak::markdown_to_html_with_plugins(md, &Options::default(), &plugins);
let html = sanitize(
let html = do_safe_html(
unsafe_html,
ExFeaturesOptions::default().sanitize,
false,
Expand Down Expand Up @@ -83,12 +84,12 @@ fn markdown_to_html_with_options<'a>(
let mut plugins = ComrakPlugins::default();
plugins.render.codefence_syntax_highlighter = Some(&inkjet_adapter);
let unsafe_html = comrak::markdown_to_html_with_plugins(md, &comrak_options, &plugins);
let html = sanitize(unsafe_html, options.features.sanitize, false, true);
let html = do_safe_html(unsafe_html, options.features.sanitize, false, true);
Ok((ok(), html).encode(env))
}
None => {
let unsafe_html = comrak::markdown_to_html(md, &comrak_options);
let html = sanitize(unsafe_html, options.features.sanitize, false, true);
let html = do_safe_html(unsafe_html, options.features.sanitize, false, true);
Ok((ok(), html).encode(env))
}
}
Expand Down Expand Up @@ -232,7 +233,7 @@ fn document_to_html(env: Env<'_>, ex_document: ExDocument) -> NifResult<Term<'_>
let options = Options::default();
comrak::format_html_with_plugins(comrak_ast, &options, &mut buffer, &plugins).unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
let html = sanitize(
let html = do_safe_html(
unsafe_html,
ExFeaturesOptions::default().sanitize,
false,
Expand Down Expand Up @@ -273,14 +274,14 @@ fn document_to_html_with_options(
comrak::format_html_with_plugins(comrak_ast, &comrak_options, &mut buffer, &plugins)
.unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
let html = sanitize(unsafe_html, options.features.sanitize, false, true);
let html = do_safe_html(unsafe_html, options.features.sanitize, false, true);
Ok((ok(), html).encode(env))
}
None => {
let mut buffer = vec![];
comrak::format_commonmark(comrak_ast, &comrak_options, &mut buffer).unwrap();
let unsafe_html = String::from_utf8(buffer).unwrap();
let html = sanitize(unsafe_html, options.features.sanitize, false, true);
let html = do_safe_html(unsafe_html, options.features.sanitize, false, true);
Ok((ok(), html).encode(env))
}
}
Expand Down Expand Up @@ -352,8 +353,25 @@ fn document_to_xml_with_options(
}
}

#[rustler::nif(schedule = "DirtyCpu")]
pub fn safe_html(
env: Env<'_>,
unsafe_html: String,
sanitize: bool,
escape_tags: bool,
escape_curly_braces_in_code: bool,
) -> NifResult<Term<'_>> {
Ok(do_safe_html(
unsafe_html,
sanitize,
escape_tags,
escape_curly_braces_in_code,
)
.encode(env))
}

// https://github.com/p-jackson/entities/blob/1d166204433c2ee7931251a5494f94c7e35be9d6/src/entities.rs
fn sanitize(
fn do_safe_html(
unsafe_html: String,
sanitize: bool,
escape_tags: bool,
Expand Down
14 changes: 14 additions & 0 deletions test/mdex_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,20 @@ defmodule MDExTest do
end
end

describe "safe html" do
test "sanitize" do
assert MDEx.safe_html("<span>tag</span><script>console.log('hello')</script>", true, false, false) == "<span>tag</span>"
end

test "escape tags" do
assert MDEx.safe_html("<span>tag</span>", false, true, false) == "&lt;span&gt;tag&lt;&#x2f;span&gt;"
end

test "escape curly braces in code tags" do
assert MDEx.safe_html("<h1>{test}</h1><code>{:foo}</code>", false, false, true) == "<h1>{test}</h1><code>&lbrace;:foo&rbrace;</code>"
end
end

describe "to_commonmark" do
test "document to commonmark with default options" do
assert MDEx.to_commonmark!(%Document{nodes: [%Heading{nodes: [%Text{literal: "Test"}]}]}) == "# Test"
Expand Down

0 comments on commit c18126d

Please sign in to comment.