use crate::markdowner::MarkdownModule; use lipgloss::{Border, utils::width}; use mq_markdown::{ListStyle, RenderOptions, UrlSurroundStyle}; use mq_view::{RenderConfig, render_markdown_with_config}; use termimad::minimad::lines; use warp::Reply; fn box_content(content: &String, width: i32) -> String { let lg_border = Border::new("─", "─", "│", "│", "╭", "╮", "╰", "╯", "", "", "", "", ""); let border_style = lipgloss::Style::new() .border(lg_border) .width(width) .padding(0, 2, 0, 2) .align_horizontal(lipgloss::position::LEFT); border_style.render(content.as_str()) } fn markdown_to_cli(content: &String) -> String { let mut mq: mq_markdown::Markdown = content.parse().expect("could not parse markdown content!"); let render_opts = RenderOptions { list_style: ListStyle::Dash, link_url_style: UrlSurroundStyle::None, link_title_style: mq_markdown::TitleSurroundStyle::Single, }; mq.set_options(render_opts); let render_conf = RenderConfig { header_full_width_highlight: false, }; let _styled_mq = mq_view::render_markdown_to_string(&mq).unwrap(); let mut writer: Vec = Vec::new(); render_markdown_with_config(&mq, &mut writer, &render_conf).unwrap(); String::from_utf8(writer).unwrap() } fn render_content(content: &String, width: i32) -> String { let md = markdown_to_cli(content); box_content(&md, width) } fn get_cli_header(page_contents: &Vec, width: i32) -> String { let header = page_contents .iter() .find(|m| m.path.file_name().unwrap_or_default().eq("header.md")); match header { Some(h) => render_content(&h.content, width), None => "".to_string(), } } fn get_cli_content(page_contents: &Vec, width: i32) -> Vec { let content = page_contents .iter() .filter(|m| m.path.file_name().unwrap_or_default().ne("header.md")); content .map(|m| render_content(&m.content, (width / 2) - 4)) .collect() } fn column_layout(mut left_column: String, mut right_column: String) -> String { let left_pad = left_column .lines() .map(|l| { String::from_utf8(strip_ansi_escapes::strip(&l)) .expect("could not strip ansi from text") .chars() .count() }) .max() .unwrap_or(0); while right_column .lines() .count() .lt(&left_column.lines().count()) { right_column = format!("{}\n", right_column); } while left_column .lines() .count() .lt(&right_column.lines().count()) { left_column = format!("{}\n", left_column); } println!( "page: {}\nsidebar: {}", right_column.lines().count(), left_column.lines().count() ); let cli_columns: Vec = left_column .lines() .zip(right_column.lines()) .map(|(left, right)| format!("{:width$} {}", left, right, width = left_pad)) .collect(); cli_columns.join("\n") } pub fn curl_response( page_contents: Vec, sidebar_contents: Vec, width: Option, ) -> Box { let w = width.unwrap_or(100); let shell_header = if width.is_none() { "curl -s beta.pogmom.me/?width=$(tput cols);exit 0\n".to_string() } else { "".to_string() }; let shell_footer = if width.is_none() { box_content( &"Did you know‽\nIf you (dangerously) pipe this output to your shell, it autosizes! more interactivity is planned in the future".to_string(), w - 4) } else { "".to_string() }; let terminal_header = get_cli_header(&page_contents, w - 4); let terminal_sidebar = get_cli_content(&sidebar_contents, w).join("\n"); let terminal_page = get_cli_content(&page_contents, w).join("\n"); let terminal_body = if w.gt(&110) { column_layout(terminal_sidebar, terminal_page) } else { format!("{}\n{}\n", terminal_sidebar, terminal_page) }; let cli_contents = format!( "{}{}\n{}\n{}\n", shell_header, terminal_header, terminal_body, shell_footer ); Box::new(warp::reply::with_status( cli_contents, warp::http::StatusCode::OK, )) }