pulldown_cmark_mdcat/terminal/capabilities/
iterm2.rs1use std::borrow::Cow;
12use std::io::{self, Result, Write};
13
14use base64::engine::general_purpose::STANDARD;
15use base64::Engine;
16use tracing::{event, instrument, Level};
17
18use crate::resources::{svg, InlineImageProtocol};
19use crate::terminal::osc::write_osc;
20use crate::ResourceUrlHandler;
21
22#[derive(Debug, Copy, Clone)]
24pub struct ITerm2Protocol;
25
26impl ITerm2Protocol {
27 pub fn set_mark<W: Write>(self, writer: &mut W) -> io::Result<()> {
29 write_osc(writer, "1337;SetMark")
30 }
31}
32
33impl InlineImageProtocol for ITerm2Protocol {
43 #[instrument(skip(self, writer, _terminal_size, resource_handler), fields(url = %url))]
44 fn write_inline_image(
45 &self,
46 writer: &mut dyn Write,
47 resource_handler: &dyn ResourceUrlHandler,
48 url: &url::Url,
49 _terminal_size: crate::TerminalSize,
50 ) -> Result<()> {
51 let mime_data = resource_handler.read_resource(url)?;
52 event!(
53 Level::DEBUG,
54 "Received data of mime type {:?}",
55 mime_data.mime_type
56 );
57
58 let name = url
61 .path_segments()
62 .and_then(|s| s.last())
63 .map(Cow::Borrowed);
64 let (name, contents) = if let Some("image/svg+xml") = mime_data.mime_type_essence() {
65 event!(Level::DEBUG, "Rendering SVG from {}", url);
66 (
67 name.map(|n| {
68 let mut name = String::new();
69 name.push_str(&n);
70 name.push_str(".png");
71 Cow::Owned(name)
72 }),
73 Cow::Owned(svg::render_svg_to_png(&mime_data.data)?),
74 )
75 } else {
76 event!(Level::DEBUG, "Rendering mime data literally");
77 (name, Cow::Borrowed(&mime_data.data))
78 };
79 let data = STANDARD.encode(contents.as_ref());
80 write_osc(
81 writer,
82 &name.map_or_else(
83 || format!("1337;File=size={};inline=1:{}", contents.len(), data),
84 |name| {
85 format!(
86 "1337;File=name={};size={};inline=1:{}",
87 STANDARD.encode(name.as_bytes()),
88 contents.len(),
89 data
90 )
91 },
92 ),
93 )
94 }
95}