use crate::config::LIB_CFG;
#[cfg(feature = "renderer")]
use crate::error::NoteError;
#[cfg(feature = "renderer")]
use crate::highlight::SyntaxPreprocessor;
use crate::settings::SETTINGS;
use parse_hyperlinks::renderer::text_links2html;
#[cfg(feature = "renderer")]
use pulldown_cmark::{html, Options, Parser};
#[cfg(feature = "renderer")]
use rst_parser::parse;
#[cfg(feature = "renderer")]
use rst_renderer::render_html;
use std::path::Path;
#[cfg(feature = "renderer")]
use std::str::from_utf8;
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum MarkupLanguage {
Markdown,
RestructuredText,
Html,
Txt,
Unknown,
None,
}
impl MarkupLanguage {
pub fn or(self, rhs: Self) -> Self {
match self {
MarkupLanguage::None => rhs,
_ => self,
}
}
pub fn render(&self, input: &str) -> String {
match self {
#[cfg(feature = "renderer")]
Self::Markdown => Self::render_md_content(input),
#[cfg(feature = "renderer")]
Self::RestructuredText => Self::render_rst_content(input),
Self::Html => input.to_string(),
_ => Self::render_txt_content(input),
}
}
#[inline]
#[cfg(feature = "renderer")]
fn render_md_content(markdown_input: &str) -> String {
let options = Options::all();
let parser = Parser::new_ext(markdown_input, options);
let parser = SyntaxPreprocessor::new(parser);
let mut html_output: String = String::with_capacity(markdown_input.len() * 3 / 2);
html::push_html(&mut html_output, parser);
html_output
}
#[inline]
#[cfg(feature = "renderer")]
fn render_rst_content(rest_input: &str) -> String {
let mut rest_input = rest_input.trim_start();
while rest_input.ends_with("\n\n") {
rest_input = &rest_input[..rest_input.len() - 1];
}
let mut html_output: Vec<u8> = Vec::with_capacity(rest_input.len() * 3 / 2);
parse(rest_input.trim_start())
.and_then(|doc| render_html(&doc, &mut html_output, false))
.map_or_else(
|e| NoteError::RstParse { msg: e.to_string() }.to_string(),
|_| from_utf8(&html_output).unwrap_or_default().to_string(),
)
}
#[inline]
fn render_txt_content(other_input: &str) -> String {
text_links2html(other_input)
}
}
impl From<&Path> for MarkupLanguage {
#[inline]
fn from(file_extension: &Path) -> Self {
let file_extension = file_extension
.extension()
.unwrap_or_default()
.to_str()
.unwrap_or_default();
Self::from(file_extension)
}
}
impl From<&str> for MarkupLanguage {
#[inline]
fn from(file_extension: &str) -> Self {
let lib_cfg = LIB_CFG.read_recursive();
for e in &lib_cfg.filename.extensions_md {
if e == file_extension {
return MarkupLanguage::Markdown;
}
}
for e in &lib_cfg.filename.extensions_rst {
if e == file_extension {
return MarkupLanguage::RestructuredText;
}
}
for e in &lib_cfg.filename.extensions_html {
if e == file_extension {
return MarkupLanguage::Html;
}
}
for e in &lib_cfg.filename.extensions_txt {
if e == file_extension {
return MarkupLanguage::Txt;
}
}
for e in &lib_cfg.filename.extensions_no_viewer {
if e == file_extension {
return MarkupLanguage::Unknown;
}
}
let settings = SETTINGS.read_recursive();
if file_extension == lib_cfg.filename.extension_default
|| file_extension == settings.extension_default
{
return MarkupLanguage::Txt;
}
MarkupLanguage::None
}
}