Skip to content

Commit

Permalink
feat: concatenate output and support base64 image encoding (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
guilhermeprokisch authored Sep 14, 2024
1 parent 97845c1 commit 19c77e7
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ansi_colours = "1.2.3"
hyperpolyglot = "0.1.7"
devicons = "0.1.0"
htmd = "0.1.6"
base64 = "0.22.1"


# The profile that 'cargo dist' will build with
Expand Down
15 changes: 14 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ mod render;
mod utils;
mod viewers;

use base64::{engine::general_purpose, Engine as _};
use std::fs;

fn main() -> std::io::Result<()> {
let (config, file_paths) = initialize_app()?;
if config.debug_mode {
Expand All @@ -29,7 +32,17 @@ fn main() -> std::io::Result<()> {
} else {
let viewer = determine_viewer(path);
if viewer.contains(&"image".to_string()) {
viewer_manager.visualize(&viewer, "", Some(path.to_str().unwrap()))?;
let img_data = fs::read(path)?;
let b64 = general_purpose::STANDARD.encode(&img_data);
let extension = path.extension().unwrap().to_str().unwrap();
let content = format!("data:image/{};base64,{}", extension, b64);

if !io::stdout().is_terminal() {
let file_name = path.file_name().unwrap().to_str().unwrap();
println!("![{}]({})", file_name, content);
} else {
viewer_manager.visualize(&viewer, &content, None)?;
}
} else {
let content = app::read_content(Some(path.to_string_lossy().into_owned()))?;
if !io::stdout().is_terminal() {
Expand Down
28 changes: 27 additions & 1 deletion src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ use std::collections::HashMap;
use std::io::{self, Write};
use std::path::PathBuf;

use base64::{engine::general_purpose, Engine as _};
use std::sync::atomic::Ordering;
use std::sync::Mutex;
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};

use url::Url;

use crate::config::get_config;
Expand Down Expand Up @@ -406,7 +408,31 @@ pub fn render_image(node: &Value) -> io::Result<()> {
}

let url = node["url"].as_str().unwrap_or("");
render_image_file(url)

if url.starts_with("data:image") {
// Handle base64 encoded image
let parts: Vec<&str> = url.split(',').collect();
if parts.len() == 2 {
let b64_data = parts[1];
let decoded = general_purpose::STANDARD
.decode(b64_data)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

// Create a temporary file
let mut temp_file = tempfile::NamedTempFile::new()?;
temp_file.write_all(&decoded)?;
let temp_path = temp_file.into_temp_path();

render_image_file(temp_path.to_str().unwrap())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid base64 image data",
))
}
} else {
render_image_file(url)
}
}

pub fn render_image_file(path: &str) -> io::Result<()> {
Expand Down
26 changes: 24 additions & 2 deletions src/viewers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::app;
use crate::config::get_config;
use crate::render::{render_code_file, render_image_file, render_markdown};
use crate::utils::detect_language;
use base64::{engine::general_purpose, Engine as _};
use devicons::{icon_for_file, File, Theme};
use std::collections::HashMap;
use std::io::{self, Write};
Expand Down Expand Up @@ -96,13 +97,34 @@ impl Viewer for CodeViewer {
struct ImageViewer;

impl Viewer for ImageViewer {
fn visualize(&self, _content: &str, file_path: Option<&str>) -> io::Result<()> {
fn visualize(&self, content: &str, file_path: Option<&str>) -> io::Result<()> {
if let Some(path) = file_path {
render_image_file(path)
} else if content.starts_with("data:image") {
// Handle base64 encoded image
let parts: Vec<&str> = content.split(',').collect();
if parts.len() == 2 {
let b64_data = parts[1];
let decoded = general_purpose::STANDARD
.decode(b64_data)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;

// Create a temporary file
let mut temp_file = tempfile::NamedTempFile::new()?;
temp_file.write_all(&decoded)?;
let temp_path = temp_file.into_temp_path();

render_image_file(temp_path.to_str().unwrap())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid base64 image data",
))
}
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"No file path provided for image rendering",
"No file path or valid base64 image data provided for image rendering",
))
}
}
Expand Down

0 comments on commit 19c77e7

Please sign in to comment.