markdown.rs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. use comrak::{create_formatter, parse_document, Arena, Options, html::ChildRendering, nodes::NodeValue};
  2. use std::fmt::Write;
  3. create_formatter!(ExternalLinkFormatter, {
  4. NodeValue::Link(ref nl) => |context, node, entering| {
  5. let skip = context.options.parse.relaxed_autolinks
  6. && node.parent().is_some_and(|p| comrak::node_matches!(p, NodeValue::Link(..)));
  7. if skip {
  8. return Ok(ChildRendering::HTML);
  9. }
  10. if entering {
  11. context.write_str("<a")?;
  12. comrak::html::render_sourcepos(context, node)?;
  13. context.write_str(" href=\"")?;
  14. let url = &nl.url;
  15. if context.options.render.r#unsafe || !comrak::html::dangerous_url(url) {
  16. if let Some(rewriter) = &context.options.extension.link_url_rewriter {
  17. context.escape_href(&rewriter.to_html(url))?;
  18. } else {
  19. context.escape_href(url)?;
  20. }
  21. }
  22. context.write_str("\"")?;
  23. if !nl.title.is_empty() {
  24. context.write_str(" title=\"")?;
  25. context.escape(&nl.title)?;
  26. context.write_str("\"")?;
  27. }
  28. context.write_str(
  29. " class=\"external-link\" target=\"_blank\" rel=\"noopener noreferrer\">",
  30. )?;
  31. } else {
  32. context.write_str("</a>")?;
  33. }
  34. },
  35. });
  36. pub fn parse_markdown(input: &str) -> String {
  37. let mut options = Options::default();
  38. options.extension.strikethrough = true;
  39. options.extension.table = true;
  40. options.extension.tasklist = true;
  41. options.extension.autolink = true;
  42. options.render.r#unsafe = true;
  43. let arena = Arena::new();
  44. let doc = parse_document(&arena, input, &options);
  45. let mut html = String::new();
  46. ExternalLinkFormatter::format_document(doc, &options, &mut html).unwrap_or_default();
  47. html
  48. }
  49. #[tauri::command]
  50. pub async fn parse_markdown_command(markdown: String) -> Result<String, String> {
  51. Ok(parse_markdown(&markdown))
  52. }