fleshed out more latex

master
Kenton Hamaluik 5 years ago
parent 78721af6b6
commit 07e86d6a0b

@ -0,0 +1,11 @@
---
title = "Task Lists"
---
You can also use [GFM](https://help.github.com/en/github/writing-on-github)-style [task lists](https://github.blog/2013-01-09-task-lists-in-gfm-issues-pulls-comments/) to indicate a TODO list:
- [ ] a task list item
- [ ] list syntax required
- [ ] normal **formatting**
- [ ] incomplete
- [x] completed

@ -57,24 +57,44 @@ fn format_text<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
output.push_str(&escape_text(text)); output.push_str(&escape_text(text));
} }
}, },
NodeValue::Code(text) => { //NodeValue::Code(text) => {
if let Ok(text) = std::str::from_utf8(text) { // if let Ok(text) = std::str::from_utf8(text) {
output.push_str("\\texttt{"); // output.push_str("\\texttt{");
output.push_str(&escape_text(text)); // output.push_str(&escape_text(text));
output.push_str("}"); // output.push_str("}");
} // }
}, //},
//NodeValue::Emph => {
// output.push_str("\\emph{");
// for child in node.children() { format_text(child, output); }
// output.push_str("}");
//},
//NodeValue::Strong => {
// output.push_str("\\textbf{");
// for child in node.children() { format_text(child, output); }
// output.push_str("}");
//},
//NodeValue::Strikethrough => {
// output.push_str("\\sout{");
// for child in node.children() { format_text(child, output); }
// output.push_str("}");
//},
//NodeValue::Superscript => {
// output.push_str("\\textsuperscript{");
// for child in node.children() { format_text(child, output); }
// output.push_str("}");
//},
_ => for child in node.children() { format_text(child, output); }, _ => for child in node.children() { format_text(child, output); },
} }
} }
fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) { fn format_node<'a>(section_offset: u32, node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
use comrak::nodes::NodeValue; use comrak::nodes::NodeValue;
match &node.data.borrow().value { match &node.data.borrow().value {
NodeValue::Document => for child in node.children() { format_node(child, output); }, NodeValue::Document => for child in node.children() { format_node(section_offset, child, output); },
NodeValue::BlockQuote => { NodeValue::BlockQuote => {
output.push_str("\\begin{quote}\n"); output.push_str("\\begin{quote}\n");
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("\\end{quote}\n"); output.push_str("\\end{quote}\n");
}, },
NodeValue::List(node_list) => { NodeValue::List(node_list) => {
@ -82,7 +102,7 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
comrak::nodes::ListType::Bullet => output.push_str("\\begin{itemize}\n"), comrak::nodes::ListType::Bullet => output.push_str("\\begin{itemize}\n"),
comrak::nodes::ListType::Ordered => output.push_str("\\begin{enumerate}\n"), comrak::nodes::ListType::Ordered => output.push_str("\\begin{enumerate}\n"),
} }
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
match node_list.list_type { match node_list.list_type {
comrak::nodes::ListType::Bullet => output.push_str("\\end{itemize}\n"), comrak::nodes::ListType::Bullet => output.push_str("\\end{itemize}\n"),
comrak::nodes::ListType::Ordered => output.push_str("\\end{enumerate}\n"), comrak::nodes::ListType::Ordered => output.push_str("\\end{enumerate}\n"),
@ -90,15 +110,19 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
}, },
NodeValue::Item(_) => { NodeValue::Item(_) => {
output.push_str("\\item "); output.push_str("\\item ");
for child in node.children() { format_node(child, output); } let mut item: String = String::default();
for child in node.children() { format_node(section_offset, child, &mut item); }
output.push_str(item.trim());
output.push_str("\n"); output.push_str("\n");
}, },
NodeValue::DescriptionList => { NodeValue::DescriptionList => {
output.push_str("\\begin{description}\n"); output.push_str("\\begin{description}\n");
for child in node.children() { format_node(child, output); } let mut items: String = String::default();
for child in node.children() { format_node(section_offset, child, &mut items); }
output.push_str(&items.replace("\n\n\n", "\n").replace("\n\n", "\n"));
output.push_str("\\end{description}\n"); output.push_str("\\end{description}\n");
}, },
NodeValue::DescriptionItem(_) => for child in node.children() { format_node(child, output); }, NodeValue::DescriptionItem(_) => for child in node.children() { format_node(section_offset, child, output); },
NodeValue::DescriptionTerm => { NodeValue::DescriptionTerm => {
output.push_str("\\item ["); output.push_str("\\item [");
let mut term: String = String::default(); let mut term: String = String::default();
@ -107,7 +131,7 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
output.push_str("] "); output.push_str("] ");
}, },
NodeValue::DescriptionDetails => { NodeValue::DescriptionDetails => {
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("\n"); output.push_str("\n");
}, },
NodeValue::CodeBlock(node_code_block) => { NodeValue::CodeBlock(node_code_block) => {
@ -133,23 +157,26 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
output.push_str("\\end{minted}\n\\end{absolutelynopagebreak}\n\n"); output.push_str("\\end{minted}\n\\end{absolutelynopagebreak}\n\n");
}, },
NodeValue::HtmlBlock(node_html_block) => { NodeValue::HtmlBlock(node_html_block) => {
log::warn!("can't handle html block, rendering it as syntax...");
let source = std::str::from_utf8(&node_html_block.literal).expect("valid utf-8");
output.push_str("\\begin{minted}[breaklines]{text}\n");
output.push_str(source);
output.push_str("\\end{minted}\n\n");
}, },
NodeValue::Paragraph => { NodeValue::Paragraph => {
for child in node.children() { for child in node.children() {
format_node(child, output); format_node(section_offset, child, output);
} }
output.push_str("\n\n"); output.push_str("\n\n");
}, },
NodeValue::Heading(node_heading) => { NodeValue::Heading(node_heading) => {
match node_heading.level { match node_heading.level + section_offset {
1 => output.push_str("\\section{"), 1 => output.push_str("\\section{"),
2 => output.push_str("\\subsection{"), 2 => output.push_str("\\subsection{"),
3 => output.push_str("\\subsubsection{"), 3 => output.push_str("\\subsubsection{"),
4 => output.push_str("\\paragraph{"), 4 => output.push_str("\\paragraph{"),
5 => output.push_str("\\subparagraph{"), 5 => output.push_str("\\subparagraph{"),
6 => output.push_str("\\textbf{"), _ => output.push_str("\\textbf{"),
_ => unreachable!()
} }
for child in node.children() { format_text(child, output); } for child in node.children() { format_text(child, output); }
output.push_str("}"); output.push_str("}");
@ -174,8 +201,16 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
output.push_str(&escape_text(text)); output.push_str(&escape_text(text));
} }
}, },
NodeValue::TaskItem(bool) => { NodeValue::TaskItem(checked) => {
let mut item: String = String::default();
for child in node.children() { format_node(section_offset, child, &mut item); }
if *checked {
output.push_str(r"$\text{\rlap{$\checkmark$}}\square$ ");
}
else {
output.push_str(r"$\square$ ");
}
output.push_str(item.trim());
}, },
NodeValue::SoftBreak => { NodeValue::SoftBreak => {
output.push_str("\n"); output.push_str("\n");
@ -191,30 +226,41 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
} }
}, },
NodeValue::HtmlInline(text) => { NodeValue::HtmlInline(text) => {
let source = std::str::from_utf8(&text).expect("valid utf-8");
log::warn!("can't handle inline html `{}`, rendering it as syntax...", source);
output.push_str("\\mintinline{html}{");
output.push_str(&escape_text(source));
output.push_str("}");
}, },
NodeValue::Emph => { NodeValue::Emph => {
output.push_str("\\emph{"); output.push_str("\\emph{");
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("}"); output.push_str("}");
}, },
NodeValue::Strong => { NodeValue::Strong => {
output.push_str("\\textbf{"); output.push_str("\\textbf{");
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("}"); output.push_str("}");
}, },
NodeValue::Strikethrough => { NodeValue::Strikethrough => {
output.push_str("\\sout{"); output.push_str("\\sout{");
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("}"); output.push_str("}");
}, },
NodeValue::Superscript => { NodeValue::Superscript => {
output.push_str("\\textsuperscript{"); output.push_str("\\textsuperscript{");
for child in node.children() { format_node(child, output); } for child in node.children() { format_node(section_offset, child, output); }
output.push_str("}"); output.push_str("}");
}, },
NodeValue::Link(node_link) => { NodeValue::Link(node_link) => {
let url = std::str::from_utf8(&node_link.url).expect("valid utf-8");
output.push_str("\\href{");
output.push_str(&escape_text(url));
output.push_str("}{");
for child in node.children() { format_text(child, output); }
output.push_str("}\\footnote{\\url{");
output.push_str(&escape_text(url));
output.push_str("}}");
}, },
NodeValue::Image(node_link) => { NodeValue::Image(node_link) => {
@ -225,7 +271,7 @@ fn format_node<'a>(node: &'a comrak::nodes::AstNode<'a>, output: &mut String) {
} }
} }
fn format_markdown(src: &str) -> Result<String, Box<dyn std::error::Error>> { fn format_markdown(section_offset: u32, src: &str) -> Result<String, Box<dyn std::error::Error>> {
let arena = comrak::Arena::new(); let arena = comrak::Arena::new();
let root = comrak::parse_document( let root = comrak::parse_document(
&arena, &arena,
@ -233,7 +279,7 @@ fn format_markdown(src: &str) -> Result<String, Box<dyn std::error::Error>> {
&COMRAK_OPTIONS); &COMRAK_OPTIONS);
let mut latex: String = String::with_capacity(src.len()); let mut latex: String = String::with_capacity(src.len());
format_node(&root, &mut latex); format_node(section_offset, &root, &mut latex);
Ok(latex) Ok(latex)
} }
@ -252,11 +298,11 @@ pub fn build<PIn: AsRef<Path>, POut: AsRef<Path>>(src: PIn, dest: POut) -> Resul
let mut book = super::load_book(&src)?; let mut book = super::load_book(&src)?;
// then convert all the markdown // then convert all the markdown
book.description = format_markdown(&book.description)?; book.description = format_markdown(0, &book.description)?;
for chapter in book.chapters.iter_mut() { for chapter in book.chapters.iter_mut() {
chapter.contents = format_markdown(&chapter.contents)?; chapter.contents = format_markdown(0, &chapter.contents)?;
for section in chapter.sections.iter_mut() { for section in chapter.sections.iter_mut() {
section.contents = format_markdown(&section.contents)?; section.contents = format_markdown(1, &section.contents)?;
} }
} }

@ -3,3 +3,7 @@ use chrono::prelude::*;
pub fn human_date(d: &DateTime<Utc>) -> askama::Result<String> { pub fn human_date(d: &DateTime<Utc>) -> askama::Result<String> {
Ok(d.format("%b %e, %Y").to_string()) Ok(d.format("%b %e, %Y").to_string())
} }
pub fn year(d: &DateTime<Utc>) -> askama::Result<String> {
Ok(d.format("%Y").to_string())
}

@ -29,10 +29,18 @@
{\par\xdef\tpd{\the\prevdepth}\egroup {\par\xdef\tpd{\the\prevdepth}\egroup
\prevdepth=\tpd} \prevdepth=\tpd}
%\makeatletter % urls
%\renewcommand{\frontmatter}{\cleardoublepage\@mainmatterfalse} \usepackage[hidelinks]{hyperref}
%\renewcommand{\mainmatter}{\cleardoublepage\@mainmattertrue}
%\makeatother % extra symbols
\usepackage{amsmath}
\usepackage{amssymb}
% make the TOC work with our preface
\makeatletter
\renewcommand{\frontmatter}{\cleardoublepage\@mainmatterfalse}
\renewcommand{\mainmatter}{\cleardoublepage\@mainmattertrue}
\makeatother
\title{ {{ front.title }} } \title{ {{ front.title }} }
\author{ {{ front.author }} } \author{ {{ front.author }} }
@ -40,10 +48,22 @@
\begin{document} \begin{document}
\frontmatter \frontmatter
\pagestyle{empty}
\maketitle \maketitle
\clearpage
% copyright
\pagestyle{empty}
\topskip0pt
\vspace*{\fill}
\begin{center}
\textcopyright{} {{ front.pubdate|year }} {{ front.author }}
\end{center}
\vspace*{\fill}
\clearpage
\tableofcontents \tableofcontents
\cleardoublepage
\chapter{Preface} \chapter{Preface}
@ -57,7 +77,7 @@
{{ chapter.contents }} {{ chapter.contents }}
{% for section in chapter.sections %} {% for section in chapter.sections %}
\chapter{ {{ section.front.title }} } \section{ {{ section.front.title }} }
{{ section.contents }} {{ section.contents }}
{% endfor %} {% endfor %}

Loading…
Cancel
Save