use crate::template::utility::{html_escape, xml_escape};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AutoEscaping {
On,
Off,
Default,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OutputFormatKind {
PlainText,
Html,
Xml,
XHtml,
JavaScript,
Json,
Css,
Rtf,
}
impl OutputFormatKind {
pub fn name(&self) -> &'static str {
match self {
OutputFormatKind::PlainText => "plainText",
OutputFormatKind::Html => "HTML",
OutputFormatKind::Xml => "XML",
OutputFormatKind::XHtml => "XHTML",
OutputFormatKind::JavaScript => "JavaScript",
OutputFormatKind::Json => "JSON",
OutputFormatKind::Css => "CSS",
OutputFormatKind::Rtf => "RTF",
}
}
pub fn parse(name: &str) -> Option<OutputFormatKind> {
match name {
"plainText" | "plaintext" => Some(OutputFormatKind::PlainText),
"HTML" | "html" => Some(OutputFormatKind::Html),
"XML" | "xml" => Some(OutputFormatKind::Xml),
"XHTML" | "xhtml" => Some(OutputFormatKind::XHtml),
"JavaScript" | "javascript" | "JS" => Some(OutputFormatKind::JavaScript),
"JSON" | "json" => Some(OutputFormatKind::Json),
"CSS" | "css" => Some(OutputFormatKind::Css),
"RTF" | "rtf" => Some(OutputFormatKind::Rtf),
_ => None,
}
}
pub fn is_markup(&self) -> bool {
!matches!(
self,
OutputFormatKind::PlainText | OutputFormatKind::Json | OutputFormatKind::JavaScript
)
}
}
pub fn escape_markup(kind: OutputFormatKind, s: &str) -> String {
match kind {
OutputFormatKind::Html | OutputFormatKind::XHtml => html_escape(s),
OutputFormatKind::Xml => xml_escape(s),
OutputFormatKind::Rtf => rtf_escape(s),
_ => s.to_string(),
}
}
pub fn rtf_escape(s: &str) -> String {
if !s.contains(['\\', '{', '}']) {
return s.to_string();
}
let mut out = String::with_capacity(s.len() + 8);
for c in s.chars() {
if c == '\\' || c == '{' || c == '}' {
out.push('\\');
}
out.push(c);
}
out
}
pub fn mime_type(kind: OutputFormatKind) -> &'static str {
match kind {
OutputFormatKind::PlainText => "text/plain",
OutputFormatKind::Html => "text/html",
OutputFormatKind::XHtml => "application/xhtml+xml",
OutputFormatKind::Xml => "application/xml",
OutputFormatKind::Rtf => "application/rtf",
OutputFormatKind::Css => "text/css",
OutputFormatKind::JavaScript => "application/javascript",
OutputFormatKind::Json => "application/json",
}
}
pub fn parse_combined_markup_format(name: &str) -> Option<Vec<OutputFormatKind>> {
if name.is_empty() {
return None;
}
if name.ends_with('}') {
let open = name.find('{')?;
let outer = parse_combined_markup_format(&name[..open])?;
let inner = parse_combined_markup_format(&name[open + 1..name.len() - 1])?;
if outer.first().is_some_and(|k| k.is_markup())
&& inner.last().is_some_and(|k| k.is_markup())
{
let mut v = outer;
v.extend(inner);
Some(v)
} else {
None
}
} else {
OutputFormatKind::parse(name).map(|k| vec![k])
}
}