diff --git a/Cargo.lock b/Cargo.lock index cee4ea9107..42bc10a140 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1489,6 +1489,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" +[[package]] +name = "htmlescape" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" + [[package]] name = "http" version = "0.1.21" @@ -2232,7 +2238,7 @@ dependencies = [ [[package]] name = "nu" -version = "0.11.0" +version = "0.11.1" dependencies = [ "clap", "crossterm 0.16.0", @@ -2312,6 +2318,7 @@ dependencies = [ "git2", "glob", "hex 0.4.0", + "htmlescape", "ichwh", "indexmap", "itertools 0.9.0", diff --git a/Cargo.toml b/Cargo.toml index 4abc5f20e7..de60d764cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "nu" -version = "0.11.0" -authors = ["Yehuda Katz ", "Jonathan Turner ", "Andrés N. Robalino "] -description = "A shell for the GitHub era" +version = "0.11.1" +authors = ["The Nu Authors"] +description = "A new kind of shell" license = "MIT" edition = "2018" readme = "README.md" diff --git a/crates/nu-cli/Cargo.toml b/crates/nu-cli/Cargo.toml index c3b5cb4090..ac6d98c6d6 100644 --- a/crates/nu-cli/Cargo.toml +++ b/crates/nu-cli/Cargo.toml @@ -44,6 +44,7 @@ getset = "0.1.0" git2 = { version = "0.11.0", default_features = false } glob = "0.3.0" hex = "0.4" +htmlescape = "0.3.1" ichwh = "0.3" indexmap = { version = "1.3.2", features = ["serde-1"] } itertools = "0.9.0" diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 75f9484c8c..75ba8ad9ed 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -313,6 +313,7 @@ pub fn create_default_context( // File format output whole_stream_command(ToBSON), whole_stream_command(ToCSV), + whole_stream_command(ToHTML), whole_stream_command(ToJSON), whole_stream_command(ToSQLite), whole_stream_command(ToDB), diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs index 58822ddf32..403e0262d9 100644 --- a/crates/nu-cli/src/commands.rs +++ b/crates/nu-cli/src/commands.rs @@ -87,6 +87,7 @@ pub(crate) mod table; pub(crate) mod tags; pub(crate) mod to_bson; pub(crate) mod to_csv; +pub(crate) mod to_html; pub(crate) mod to_json; pub(crate) mod to_sqlite; pub(crate) mod to_toml; @@ -191,6 +192,7 @@ pub(crate) use table::Table; pub(crate) use tags::Tags; pub(crate) use to_bson::ToBSON; pub(crate) use to_csv::ToCSV; +pub(crate) use to_html::ToHTML; pub(crate) use to_json::ToJSON; pub(crate) use to_sqlite::ToDB; pub(crate) use to_sqlite::ToSQLite; diff --git a/crates/nu-cli/src/commands/to_html.rs b/crates/nu-cli/src/commands/to_html.rs new file mode 100644 index 0000000000..d18cb0024e --- /dev/null +++ b/crates/nu-cli/src/commands/to_html.rs @@ -0,0 +1,101 @@ +use crate::commands::WholeStreamCommand; +use crate::data::value::format_leaf; +use crate::prelude::*; +use futures::StreamExt; +use nu_errors::ShellError; +use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value}; +use nu_source::AnchorLocation; + +pub struct ToHTML; + +impl WholeStreamCommand for ToHTML { + fn name(&self) -> &str { + "to-html" + } + + fn signature(&self) -> Signature { + Signature::build("to-html") + } + + fn usage(&self) -> &str { + "Convert table into simple HTML" + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + to_html(args, registry) + } +} + +fn to_html(args: CommandArgs, registry: &CommandRegistry) -> Result { + let args = args.evaluate_once(registry)?; + let name_tag = args.name_tag(); + //let name_span = name_tag.span; + let stream = async_stream! { + let input: Vec = args.input.values.collect().await; + let headers = nu_protocol::merge_descriptors(&input); + let mut output_string = "".to_string(); + + if !headers.is_empty() && (headers.len() > 1 || headers[0] != "") { + output_string.push_str(""); + + output_string.push_str(""); + for header in &headers { + output_string.push_str(""); + } + output_string.push_str(""); + } + + for row in input { + match row.value { + UntaggedValue::Primitive(Primitive::Binary(b)) => { + // This might be a bit much, but it's fun :) + match row.tag.anchor { + Some(AnchorLocation::Url(f)) | + Some(AnchorLocation::File(f)) => { + let extension = f.split('.').last().map(String::from); + match extension { + Some(s) if ["png", "jpg", "bmp", "gif", "tiff"].contains(&s.as_str()) => { + output_string.push_str(""); + } + _ => {} + } + } + _ => {} + } + } + UntaggedValue::Row(row) => { + output_string.push_str(""); + for header in &headers { + let data = row.get_data(header); + output_string.push_str(""); + } + output_string.push_str(""); + } + p => { + output_string.push_str(&(htmlescape::encode_minimal(&format_leaf(&p).plain_string(100_000)).replace("\n", "
"))); + } + } + } + + if !headers.is_empty() && (headers.len() > 1 || headers[0] != "") { + output_string.push_str("
"); + output_string.push_str(&htmlescape::encode_minimal(&header)); + output_string.push_str("
"); + output_string.push_str(&format_leaf(data.borrow()).plain_string(100_000)); + output_string.push_str("
"); + } + output_string.push_str(""); + + yield ReturnSuccess::value(UntaggedValue::string(output_string).into_value(name_tag)); + }; + + Ok(stream.to_output_stream()) +} diff --git a/crates/nu-cli/tests/format_conversions/html.rs b/crates/nu-cli/tests/format_conversions/html.rs new file mode 100644 index 0000000000..07cfc5b66f --- /dev/null +++ b/crates/nu-cli/tests/format_conversions/html.rs @@ -0,0 +1,28 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn out_html_simple() { + let actual = nu!( + cwd: ".", pipeline( + r#" + echo 3 | to-html + "# + )); + + assert_eq!(actual, "3"); +} + +#[test] +fn out_html_table() { + let actual = nu!( + cwd: ".", pipeline( + r#" + echo '{"name": "jason"}' | from-json | to-html + "# + )); + + assert_eq!( + actual, + "
name
jason
" + ); +} diff --git a/crates/nu-cli/tests/format_conversions/mod.rs b/crates/nu-cli/tests/format_conversions/mod.rs index c222f449d4..66c8e97b13 100644 --- a/crates/nu-cli/tests/format_conversions/mod.rs +++ b/crates/nu-cli/tests/format_conversions/mod.rs @@ -1,5 +1,6 @@ mod bson; mod csv; +mod html; mod json; mod ods; mod sqlite;