Skip to content

Commit

Permalink
fix: make html_encode optional
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed Sep 28, 2024
1 parent c488b76 commit cc629ee
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 52 deletions.
9 changes: 5 additions & 4 deletions cli/src/cli/generate/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ pub struct Markdown {
#[clap(long)]
url_prefix: Option<String>,

// /// Escape HTML in markdown
// #[clap(long)]
// html_escape: bool,
/// Escape HTML in markdown
#[clap(long)]
html_encode: bool,

/// Output markdown files to this directory
#[clap(long, value_hint = clap::ValueHint::DirPath)]
out_dir: Option<PathBuf>,
Expand All @@ -40,7 +41,7 @@ impl Markdown {
Ok(())
};
let (spec, _) = Spec::parse_file(&self.file)?;
let mut ctx = MarkdownRenderer::new(&spec);
let mut ctx = MarkdownRenderer::new(&spec).with_html_encode(self.html_encode);
if let Some(url_prefix) = &self.url_prefix {
ctx = ctx.with_url_prefix(url_prefix);
}
Expand Down
5 changes: 1 addition & 4 deletions lib/src/docs/markdown/arg.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::docs::markdown::renderer::MarkdownRenderer;
use crate::docs::markdown::tera::TERA;
use crate::error::UsageErr;
use crate::SpecArg;

impl MarkdownRenderer {
pub fn render_arg(&self, arg: &SpecArg) -> Result<String, UsageErr> {
let tera = TERA.clone();
let mut ctx = self.clone();
ctx.insert("arg", arg);

Ok(tera.render("arg_template.md.tera", &ctx.tera_ctx())?)
ctx.render("arg_template.md.tera")
}
}

Expand Down
5 changes: 1 addition & 4 deletions lib/src/docs/markdown/cmd.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::docs::markdown::renderer::MarkdownRenderer;
use crate::docs::markdown::tera::TERA;
use crate::error::UsageErr;
use crate::SpecCommand;

impl MarkdownRenderer {
pub fn render_cmd(&self, cmd: &SpecCommand) -> Result<String, UsageErr> {
let mut ctx = self.clone();

ctx.insert("cmd", cmd);

Ok(TERA.render("cmd_template.md.tera", &ctx.tera_ctx())?)
ctx.render("cmd_template.md.tera")
}
}

Expand Down
5 changes: 1 addition & 4 deletions lib/src/docs/markdown/flag.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::docs::markdown::renderer::MarkdownRenderer;
use crate::docs::markdown::tera::TERA;
use crate::error::UsageErr;
use crate::SpecFlag;

impl MarkdownRenderer {
pub fn render_flag(&self, flag: &SpecFlag) -> Result<String, UsageErr> {
let tera = TERA.clone();
let mut ctx = self.clone();
ctx.insert("flag", &flag);

Ok(tera.render("flag_template.md.tera", &ctx.tera_ctx())?)
ctx.render("flag_template.md.tera")
}
}

Expand Down
48 changes: 46 additions & 2 deletions lib/src/docs/markdown/renderer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::docs::markdown::tera::TERA;
use crate::error::UsageErr;
use crate::Spec;
use itertools::Itertools;
use serde::Serialize;
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct MarkdownRenderer {
Expand All @@ -8,6 +12,7 @@ pub struct MarkdownRenderer {
pub(crate) spec: Spec,
url_prefix: Option<String>,
tera_ctx: tera::Context,
html_encode: bool,
}

impl MarkdownRenderer {
Expand All @@ -18,6 +23,7 @@ impl MarkdownRenderer {
spec: spec.clone(),
tera_ctx: tera::Context::new(),
url_prefix: None,
html_encode: true,
}
}

Expand All @@ -36,17 +42,55 @@ impl MarkdownRenderer {
self
}

pub fn with_html_encode(mut self, html_encode: bool) -> Self {
self.html_encode = html_encode;
self
}

pub(crate) fn insert<T: Serialize + ?Sized, S: Into<String>>(&mut self, key: S, val: &T) {
self.tera_ctx.insert(key, val);
}

pub(crate) fn tera_ctx(&self) -> tera::Context {
fn tera_ctx(&self) -> tera::Context {
let mut ctx = self.tera_ctx.clone();
ctx.insert("header_level", &self.header_level);
ctx.insert("multi", &self.multi);
ctx.insert("spec", &self.spec);
ctx.insert("url_prefix", &self.url_prefix);
ctx.insert("html_escape", &true);
ctx.insert("html_encode", &self.html_encode);
ctx
}

pub(crate) fn render(&self, template_name: &str) -> Result<String, UsageErr> {
let mut tera = TERA.clone();

let html_encode = self.html_encode;
tera.register_filter(
"escape_md",
move |value: &tera::Value, _: &HashMap<String, tera::Value>| {
let value = value.as_str().unwrap();
let value = value
.lines()
.map(|line| {
if !html_encode || line.starts_with(" ") {
return line.to_string();
}
// replace '<' with '&lt;' but not inside code blocks
xx::regex!(r"(`[^`]*`)|(<)")
.replace_all(line, |caps: &regex::Captures| {
if caps.get(1).is_some() {
caps.get(1).unwrap().as_str().to_string()
} else {
"&lt;".to_string()
}
})
.to_string()
})
.join("\n");
Ok(value.into())
},
);

Ok(tera.render(template_name, &self.tera_ctx())?)
}
}
9 changes: 2 additions & 7 deletions lib/src/docs/markdown/spec.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
use crate::docs::markdown::renderer::MarkdownRenderer;
use crate::docs::markdown::tera::TERA;
use crate::error::UsageErr;

impl MarkdownRenderer {
pub fn render_spec(&self) -> Result<String, UsageErr> {
let mut ctx = self.clone();

ctx.insert("all_commands", &self.spec.cmd.all_subcommands());

Ok(TERA.render("spec_template.md.tera", &ctx.tera_ctx())?)
ctx.render("spec_template.md.tera")
}

pub fn render_index(&self) -> Result<String, UsageErr> {
let mut ctx = self.clone();

ctx.multi = false;
ctx.insert("all_commands", &self.spec.cmd.all_subcommands());

Ok(TERA.render("index_template.md.tera", &ctx.tera_ctx())?)
ctx.render("index_template.md.tera")
}
}

Expand Down
27 changes: 0 additions & 27 deletions lib/src/docs/markdown/tera.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use itertools::Itertools;
use once_cell::sync::Lazy;
use std::collections::HashMap;
use tera::Tera;
Expand All @@ -24,31 +23,5 @@ pub(crate) static TERA: Lazy<Tera> = Lazy::new(|| {
},
);

tera.register_filter(
"escape_md",
move |value: &tera::Value, _: &HashMap<String, tera::Value>| {
let value = value.as_str().unwrap();
let value = value
.lines()
.map(|line| {
if line.starts_with(" ") {
return line.to_string();
}
// replace '<' with '&lt;' but not inside code blocks
xx::regex!(r"(`[^`]*`)|(<)")
.replace_all(line, |caps: &regex::Captures| {
if caps.get(1).is_some() {
caps.get(1).unwrap().as_str().to_string()
} else {
"&lt;".to_string()
}
})
.to_string()
})
.join("\n");
Ok(value.into())
},
);

tera
});

0 comments on commit cc629ee

Please sign in to comment.