Просмотр исходного кода

fix(app): open markdown links in external browser

adamelmore 3 недель назад
Родитель
Сommit
3297e5230e
1 измененных файлов с 45 добавлено и 2 удалено
  1. 45 2
      packages/desktop/src-tauri/src/markdown.rs

+ 45 - 2
packages/desktop/src-tauri/src/markdown.rs

@@ -1,4 +1,43 @@
-use comrak::{markdown_to_html, Options};
+use comrak::{create_formatter, parse_document, Arena, Options, html::ChildRendering, nodes::NodeValue};
+use std::fmt::Write;
+
+create_formatter!(ExternalLinkFormatter, {
+    NodeValue::Link(ref nl) => |context, node, entering| {
+        let skip = context.options.parse.relaxed_autolinks
+            && node.parent().is_some_and(|p| comrak::node_matches!(p, NodeValue::Link(..)));
+        if skip {
+            return Ok(ChildRendering::HTML);
+        }
+
+        if entering {
+            context.write_str("<a")?;
+            comrak::html::render_sourcepos(context, node)?;
+
+            context.write_str(" href=\"")?;
+            let url = &nl.url;
+            if context.options.render.r#unsafe || !comrak::html::dangerous_url(url) {
+                if let Some(rewriter) = &context.options.extension.link_url_rewriter {
+                    context.escape_href(&rewriter.to_html(url))?;
+                } else {
+                    context.escape_href(url)?;
+                }
+            }
+            context.write_str("\"")?;
+
+            if !nl.title.is_empty() {
+                context.write_str(" title=\"")?;
+                context.escape(&nl.title)?;
+                context.write_str("\"")?;
+            }
+
+            context.write_str(
+                " class=\"external-link\" target=\"_blank\" rel=\"noopener noreferrer\">",
+            )?;
+        } else {
+            context.write_str("</a>")?;
+        }
+    },
+});
 
 pub fn parse_markdown(input: &str) -> String {
     let mut options = Options::default();
@@ -8,7 +47,11 @@ pub fn parse_markdown(input: &str) -> String {
     options.extension.autolink = true;
     options.render.r#unsafe = true;
 
-    markdown_to_html(input, &options)
+    let arena = Arena::new();
+    let doc = parse_document(&arena, input, &options);
+    let mut html = String::new();
+    ExternalLinkFormatter::format_document(doc, &options, &mut html).unwrap_or_default();
+    html
 }
 
 #[tauri::command]