From 78721af6b6213dc065b3a181de7ed09b1cbf34e5 Mon Sep 17 00:00:00 2001 From: Kenton Hamaluik Date: Fri, 6 Dec 2019 23:03:14 -0700 Subject: [PATCH] tidied syntax highlighting --- src/latex.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- templates/book.tex | 33 ++++++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/latex.rs b/src/latex.rs index fcb084b..16cf9e7 100644 --- a/src/latex.rs +++ b/src/latex.rs @@ -36,18 +36,31 @@ struct BookTemplate<'a, 'b, 'c> { chapters: Vec<&'c Chapter>, } +fn escape_text(text: &str) -> String { + text + .replace(r"\", r"\textbackslash{}") + .replace(r"#", r"\#") + .replace(r"$", r"\$") + .replace(r"%", r"\%") + .replace(r"&", r"\&") + .replace(r"{", r"\{") + .replace(r"}", r"\}") + .replace(r"^", r"\textasciicircum{}") + .replace(r"~", r"\textasciitilde{}") +} + fn format_text<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) { use comrak::nodes::NodeValue; match &node.data.borrow().value { NodeValue::Text(text) => { if let Ok(text) = std::str::from_utf8(text) { - output.push_str(text); + output.push_str(&escape_text(text)); } }, NodeValue::Code(text) => { if let Ok(text) = std::str::from_utf8(text) { output.push_str("\\texttt{"); - output.push_str(text); + output.push_str(&escape_text(text)); output.push_str("}"); } }, @@ -98,7 +111,26 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) { output.push_str("\n"); }, NodeValue::CodeBlock(node_code_block) => { - + let lang = std::str::from_utf8(&node_code_block.info).expect("valid utf-8"); + let source = std::str::from_utf8(&node_code_block.literal).expect("valid utf-8"); + + if lang.to_lowercase() == "plantuml" { + log::debug!("TODO: render plantuml"); + return; + } + else if lang.to_lowercase() == "katex" { + output.push_str("\\begin{equation}\n"); + output.push_str(source); + output.push_str("\\end{equation}\n"); + return; + } + + let lang = if lang.trim().is_empty() { "text" } else { lang }; + output.push_str("\\begin{absolutelynopagebreak}\n\\begin{minted}[breaklines]{"); + output.push_str(&escape_text(lang)); + output.push_str("}\n"); + output.push_str(source); + output.push_str("\\end{minted}\n\\end{absolutelynopagebreak}\n\n"); }, NodeValue::HtmlBlock(node_html_block) => { @@ -139,7 +171,7 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) { }, NodeValue::Text(text) => { if let Ok(text) = std::str::from_utf8(text) { - output.push_str(text); + output.push_str(&escape_text(text)); } }, NodeValue::TaskItem(bool) => { @@ -154,7 +186,7 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) { NodeValue::Code(text) => { if let Ok(text) = std::str::from_utf8(text) { output.push_str("\\verb|"); - output.push_str(text); + output.push_str(&escape_text(text)); output.push_str("|"); } }, @@ -223,6 +255,9 @@ pub fn build, POut: AsRef>(src: PIn, dest: POut) -> Resul book.description = format_markdown(&book.description)?; for chapter in book.chapters.iter_mut() { chapter.contents = format_markdown(&chapter.contents)?; + for section in chapter.sections.iter_mut() { + section.contents = format_markdown(§ion.contents)?; + } } // and render to a template diff --git a/templates/book.tex b/templates/book.tex index 8adfbcf..7926cb9 100644 --- a/templates/book.tex +++ b/templates/book.tex @@ -10,12 +10,29 @@ \usepackage{fontspec} \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \setmainfont{Crimson} -\setmonofont{Fira Mono} +\setsansfont{Poppins} +\setmonofont{Source Code Pro} -\makeatletter -\renewcommand{\frontmatter}{\cleardoublepage\@mainmatterfalse} -\renewcommand{\mainmatter}{\cleardoublepage\@mainmattertrue} -\makeatother +% sans-serif fonts in the headers +\usepackage{sectsty} +\allsectionsfont{\sffamily} + +% syntax highlighting +\usepackage{minted} +\usemintedstyle{vs} + +% prevent page breaks +% https://tex.stackexchange.com/a/94702 +\newenvironment{absolutelynopagebreak} + {\par\nobreak\vfil\penalty0\vfilneg + \vtop\bgroup} + {\par\xdef\tpd{\the\prevdepth}\egroup + \prevdepth=\tpd} + +%\makeatletter +%\renewcommand{\frontmatter}{\cleardoublepage\@mainmatterfalse} +%\renewcommand{\mainmatter}{\cleardoublepage\@mainmattertrue} +%\makeatother \title{ {{ front.title }} } \author{ {{ front.author }} } @@ -39,6 +56,12 @@ {{ chapter.contents }} +{% for section in chapter.sections %} +\chapter{ {{ section.front.title }} } + +{{ section.contents }} +{% endfor %} + {% endfor %} \end{document}