mirror of
https://github.com/nushell/nushell.git
synced 2025-08-16 18:41:41 +02:00
Add --raw
flag to to html
(#16373)
Works towards #16347 however more work may be required first # Description Adds a `--raw` flag to `to html`. This stops the resulting html content being escaped # User-Facing Changes # Tests + Formatting # After Submitting
This commit is contained in:
@ -3,7 +3,12 @@ use nu_protocol::engine::Command;
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_examples(cmd: impl Command + 'static) {
|
||||
test_examples::test_examples(cmd);
|
||||
test_examples::test_examples(cmd, &[]);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn test_examples_with_commands(cmd: impl Command + 'static, commands: &[&dyn Command]) {
|
||||
test_examples::test_examples(cmd, commands);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -21,10 +26,10 @@ mod test_examples {
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub fn test_examples(cmd: impl Command + 'static) {
|
||||
pub fn test_examples(cmd: impl Command + 'static, commands: &[&dyn Command]) {
|
||||
let examples = cmd.examples();
|
||||
let signature = cmd.signature();
|
||||
let mut engine_state = make_engine_state(cmd.clone_box());
|
||||
let mut engine_state = make_engine_state(cmd.clone_box(), commands);
|
||||
|
||||
let cwd = std::env::current_dir().expect("Could not get current working directory.");
|
||||
|
||||
@ -38,7 +43,7 @@ mod test_examples {
|
||||
check_example_input_and_output_types_match_command_signature(
|
||||
&example,
|
||||
&cwd,
|
||||
&mut make_engine_state(cmd.clone_box()),
|
||||
&mut make_engine_state(cmd.clone_box(), commands),
|
||||
&signature.input_output_types,
|
||||
signature.operates_on_cell_paths(),
|
||||
),
|
||||
@ -57,7 +62,7 @@ mod test_examples {
|
||||
);
|
||||
}
|
||||
|
||||
fn make_engine_state(cmd: Box<dyn Command>) -> Box<EngineState> {
|
||||
fn make_engine_state(cmd: Box<dyn Command>, commands: &[&dyn Command]) -> Box<EngineState> {
|
||||
let mut engine_state = Box::new(EngineState::new());
|
||||
|
||||
let delta = {
|
||||
@ -69,6 +74,10 @@ mod test_examples {
|
||||
working_set.add_decl(Box::new(nu_cmd_lang::If));
|
||||
working_set.add_decl(Box::new(nu_command::MathRound));
|
||||
|
||||
for command in commands {
|
||||
working_set.add_decl(command.clone_box());
|
||||
}
|
||||
|
||||
// Adding the command that is being tested to the working set
|
||||
working_set.add_decl(cmd);
|
||||
working_set.render()
|
||||
|
@ -109,18 +109,26 @@ impl Command for ToHtml {
|
||||
"produce a color table of all available themes",
|
||||
Some('l'),
|
||||
)
|
||||
.switch("raw", "do not escape html tags", Some('r'))
|
||||
.category(Category::Formats)
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Outputs an HTML string representing the contents of this table",
|
||||
description: "Outputs an HTML string representing the contents of this table",
|
||||
example: "[[foo bar]; [1 2]] | to html",
|
||||
result: Some(Value::test_string(
|
||||
r#"<html><style>body { background-color:white;color:black; }</style><body><table><thead><tr><th>foo</th><th>bar</th></tr></thead><tbody><tr><td>1</td><td>2</td></tr></tbody></table></body></html>"#,
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Outputs an HTML string using a record of xml data",
|
||||
example: r#"{tag: a attributes: { style: "color: red" } content: ["hello!"] } | to xml | to html --raw"#,
|
||||
result: Some(Value::test_string(
|
||||
r#"<html><style>body { background-color:white;color:black; }</style><body><a style="color: red">hello!</a></body></html>"#,
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Optionally, only output the html for the content itself",
|
||||
example: "[[foo bar]; [1 2]] | to html --partial",
|
||||
@ -254,6 +262,7 @@ fn to_html(
|
||||
let dark = call.has_flag(engine_state, stack, "dark")?;
|
||||
let partial = call.has_flag(engine_state, stack, "partial")?;
|
||||
let list = call.has_flag(engine_state, stack, "list")?;
|
||||
let raw = call.has_flag(engine_state, stack, "raw")?;
|
||||
let theme: Option<Spanned<String>> = call.get_flag(engine_state, stack, "theme")?;
|
||||
let config = &stack.get_config(engine_state);
|
||||
|
||||
@ -319,15 +328,15 @@ fn to_html(
|
||||
let inner_value = match vec_of_values.len() {
|
||||
0 => String::default(),
|
||||
1 => match headers {
|
||||
Some(headers) => html_table(vec_of_values, headers, config),
|
||||
Some(headers) => html_table(vec_of_values, headers, raw, config),
|
||||
None => {
|
||||
let value = &vec_of_values[0];
|
||||
html_value(value.clone(), config)
|
||||
html_value(value.clone(), raw, config)
|
||||
}
|
||||
},
|
||||
_ => match headers {
|
||||
Some(headers) => html_table(vec_of_values, headers, config),
|
||||
None => html_list(vec_of_values, config),
|
||||
Some(headers) => html_table(vec_of_values, headers, raw, config),
|
||||
None => html_list(vec_of_values, raw, config),
|
||||
},
|
||||
};
|
||||
|
||||
@ -395,19 +404,19 @@ fn theme_demo(span: Span) -> PipelineData {
|
||||
})
|
||||
}
|
||||
|
||||
fn html_list(list: Vec<Value>, config: &Config) -> String {
|
||||
fn html_list(list: Vec<Value>, raw: bool, config: &Config) -> String {
|
||||
let mut output_string = String::new();
|
||||
output_string.push_str("<ol>");
|
||||
for value in list {
|
||||
output_string.push_str("<li>");
|
||||
output_string.push_str(&html_value(value, config));
|
||||
output_string.push_str(&html_value(value, raw, config));
|
||||
output_string.push_str("</li>");
|
||||
}
|
||||
output_string.push_str("</ol>");
|
||||
output_string
|
||||
}
|
||||
|
||||
fn html_table(table: Vec<Value>, headers: Vec<String>, config: &Config) -> String {
|
||||
fn html_table(table: Vec<Value>, headers: Vec<String>, raw: bool, config: &Config) -> String {
|
||||
let mut output_string = String::new();
|
||||
|
||||
output_string.push_str("<table>");
|
||||
@ -430,7 +439,7 @@ fn html_table(table: Vec<Value>, headers: Vec<String>, config: &Config) -> Strin
|
||||
.cloned()
|
||||
.unwrap_or_else(|| Value::nothing(span));
|
||||
output_string.push_str("<td>");
|
||||
output_string.push_str(&html_value(data, config));
|
||||
output_string.push_str(&html_value(data, raw, config));
|
||||
output_string.push_str("</td>");
|
||||
}
|
||||
output_string.push_str("</tr>");
|
||||
@ -441,7 +450,7 @@ fn html_table(table: Vec<Value>, headers: Vec<String>, config: &Config) -> Strin
|
||||
output_string
|
||||
}
|
||||
|
||||
fn html_value(value: Value, config: &Config) -> String {
|
||||
fn html_value(value: Value, raw: bool, config: &Config) -> String {
|
||||
let mut output_string = String::new();
|
||||
match value {
|
||||
Value::Binary { val, .. } => {
|
||||
@ -450,11 +459,22 @@ fn html_value(value: Value, config: &Config) -> String {
|
||||
output_string.push_str(&output);
|
||||
output_string.push_str("</pre>");
|
||||
}
|
||||
other => output_string.push_str(
|
||||
&v_htmlescape::escape(&other.to_abbreviated_string(config))
|
||||
.to_string()
|
||||
.replace('\n', "<br>"),
|
||||
),
|
||||
other => {
|
||||
if raw {
|
||||
output_string.push_str(
|
||||
&other
|
||||
.to_abbreviated_string(config)
|
||||
.to_string()
|
||||
.replace('\n', "<br>"),
|
||||
)
|
||||
} else {
|
||||
output_string.push_str(
|
||||
&v_htmlescape::escape(&other.to_abbreviated_string(config))
|
||||
.to_string()
|
||||
.replace('\n', "<br>"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
output_string
|
||||
}
|
||||
@ -717,9 +737,10 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_examples() {
|
||||
use crate::test_examples;
|
||||
use crate::test_examples_with_commands;
|
||||
use nu_command::ToXml;
|
||||
|
||||
test_examples(ToHtml {})
|
||||
test_examples_with_commands(ToHtml {}, &[&ToXml])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -4,4 +4,4 @@ pub mod extra;
|
||||
pub use extra::*;
|
||||
|
||||
#[cfg(test)]
|
||||
pub use example_test::test_examples;
|
||||
pub use example_test::{test_examples, test_examples_with_commands};
|
||||
|
Reference in New Issue
Block a user