diff --git a/src/html/home.rs b/src/html/home.rs
index 0c39503..3030f4b 100644
--- a/src/html/home.rs
+++ b/src/html/home.rs
@@ -1,8 +1,8 @@
use camino::Utf8Path;
-use hauchiwa::{Link, LinkDate, Sack};
+use hauchiwa::Sack;
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
-use crate::{html::Post, text::md::parse};
+use crate::{html::Post, text::md::parse, Link, LinkDate};
const INTRO: &str = r#"
## かもし
diff --git a/src/html/list.rs b/src/html/list.rs
index 46ab536..1fdfdce 100644
--- a/src/html/list.rs
+++ b/src/html/list.rs
@@ -1,7 +1,7 @@
-use hauchiwa::{LinkDate, Sack};
+use hauchiwa::Sack;
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
-use crate::html::page;
+use crate::{html::page, LinkDate};
pub fn list<'s, 'g, 'html>(
sack: &'s Sack,
diff --git a/src/html/misc.rs b/src/html/misc.rs
index 2565fed..0d54ce1 100644
--- a/src/html/misc.rs
+++ b/src/html/misc.rs
@@ -1,6 +1,10 @@
-use hauchiwa::{Outline, Sack, TreePage};
+use std::collections::HashMap;
+
+use camino::Utf8Path;
+use hauchiwa::{Outline, Sack};
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
+use crate::{html::Wiki, Link};
/// Render the outline for a document
pub(crate) fn show_outline(outline: Outline) -> impl Renderable {
@@ -41,9 +45,50 @@ pub(crate) fn emit_bibliography(bib: Vec) -> impl Renderable {
)
}
+#[derive(Debug)]
+pub struct TreePage {
+ pub link: Option,
+ pub subs: HashMap,
+}
+
+impl TreePage {
+ fn new() -> Self {
+ TreePage {
+ link: None,
+ subs: HashMap::new(),
+ }
+ }
+
+ fn add_link(&mut self, link: &Link) {
+ let mut ptr = self;
+ for part in link.path.iter().skip(1) {
+ ptr = ptr.subs.entry(part.to_string()).or_insert(TreePage::new());
+ }
+ ptr.link = Some(link.clone());
+ }
+
+ fn from_iter(iter: impl Iterator- ) -> Self {
+ let mut tree = Self::new();
+ for link in iter {
+ tree.add_link(&link);
+ }
+
+ tree
+ }
+}
+
/// Render the page tree
pub(crate) fn show_page_tree(sack: &Sack, glob: &str) -> impl Renderable {
- let tree = sack.get_tree(glob);
+ let tree =
+ TreePage::from_iter(
+ sack.get_meta::(glob)
+ .into_iter()
+ .map(|(path, meta)| Link {
+ path: Utf8Path::new("/").join(path),
+ name: meta.title.clone(),
+ desc: None,
+ }),
+ );
maud_move!(
h2 .link-tree__heading {
diff --git a/src/html/mod.rs b/src/html/mod.rs
index 721b343..690d881 100644
--- a/src/html/mod.rs
+++ b/src/html/mod.rs
@@ -9,19 +9,19 @@ pub mod wiki;
use std::collections::HashMap;
-use camino::{Utf8Path, Utf8PathBuf};
-use chrono::{DateTime, Datelike, Utc};
-use hauchiwa::{Bibliography, Link, LinkDate, Linkable, Outline, Sack};
-use hayagriva::Library;
+use camino::Utf8Path;
+use chrono::Datelike;
+use hauchiwa::{Bibliography, Outline, Sack};
use hypertext::{html_elements, maud, maud_move, GlobalAttributes, Raw, Renderable};
pub(crate) use home::home;
use post::article;
pub(crate) use post::Post;
-use serde::Deserialize;
pub(crate) use slideshow::Slideshow;
pub(crate) use wiki::Wiki;
+use crate::LinkDate;
+
fn navbar() -> impl Renderable {
static ITEMS: &[(&str, &str)] = &[
("Posts", "/posts/"),
@@ -198,7 +198,7 @@ where
)
}
-pub(crate) fn search<'s, 'html>(sack: &'s Sack) -> String {
+pub(crate) fn search(sack: &Sack) -> String {
page(
sack,
maud!(
@@ -222,7 +222,7 @@ pub fn as_html(
flox(&meta.title, parsed, sack, outline, bibliography)
}
-pub(crate) fn flox<'p, 's, 'html>(
+pub(crate) fn flox(
title: &str,
parsed: &str,
sack: &Sack,
diff --git a/src/html/post.rs b/src/html/post.rs
index 5bc72cd..8da59a3 100644
--- a/src/html/post.rs
+++ b/src/html/post.rs
@@ -1,6 +1,6 @@
-use camino::{Utf8Path, Utf8PathBuf};
+use camino::Utf8Path;
use chrono::{DateTime, Utc};
-use hauchiwa::{Bibliography, Link, LinkDate, Linkable, Outline, Sack};
+use hauchiwa::{Bibliography, Outline, Sack};
use hayagriva::Library;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
@@ -8,103 +8,92 @@ use serde::Deserialize;
/// Represents a simple post.
#[derive(Deserialize, Debug, Clone)]
pub struct Post {
- pub title: String,
- #[serde(with = "super::isodate")]
- pub date: DateTime,
- pub desc: Option,
- pub scripts: Option>,
+ pub title: String,
+ #[serde(with = "super::isodate")]
+ pub date: DateTime,
+ pub desc: Option,
+ pub scripts: Option>,
}
pub fn parse_content(
- content: &str,
- sack: &Sack,
- path: &Utf8Path,
- library: Option<&Library>,
+ content: &str,
+ sack: &Sack,
+ path: &Utf8Path,
+ library: Option<&Library>,
) -> (String, Outline, Bibliography) {
- crate::text::md::parse(content, sack, path, library)
+ crate::text::md::parse(content, sack, path, library)
}
pub fn as_html(
- meta: &Post,
- parsed: &str,
- sack: &Sack,
- outline: Outline,
- bibliography: Bibliography,
+ meta: &Post,
+ parsed: &str,
+ sack: &Sack,
+ outline: Outline,
+ bibliography: Bibliography,
) -> String {
- post(meta, parsed, sack, outline, bibliography)
- .unwrap()
- .render()
- .into()
-}
-
-pub fn as_link(meta: &Post, path: Utf8PathBuf) -> Option {
- Some(Linkable::Date(LinkDate {
- link: Link {
- path,
- name: meta.title.to_owned(),
- desc: meta.desc.to_owned(),
- },
- date: meta.date.to_owned(),
- }))
+ post(meta, parsed, sack, outline, bibliography)
+ .unwrap()
+ .render()
+ .into()
}
pub fn post<'s, 'p, 'html>(
- meta: &'p Post,
- parsed: &'p str,
- sack: &'s Sack,
- outline: Outline,
- bibliography: Bibliography,
+ meta: &'p Post,
+ parsed: &'p str,
+ sack: &'s Sack,
+ outline: Outline,
+ bibliography: Bibliography,
) -> Result
where
- 's: 'html,
- 'p: 'html,
+ 's: 'html,
+ 'p: 'html,
{
- let main = maud_move!(
- main {
- (article(&meta.title, parsed, sack, outline, bibliography))
- }
- );
+ let main = maud_move!(
+ main {
+ (article(&meta.title, parsed, sack, outline, bibliography))
+ }
+ );
- crate::html::page(sack, main, meta.title.clone(), meta.scripts.as_deref())
+ crate::html::page(sack, main, meta.title.clone(), meta.scripts.as_deref())
}
pub fn article<'p, 's, 'html>(
- title: &'p str,
- parsed: &'p str,
- _: &'s Sack,
- outline: Outline,
- bibliography: Bibliography,
+ title: &'p str,
+ parsed: &'p str,
+ _: &'s Sack,
+ outline: Outline,
+ bibliography: Bibliography,
) -> impl Renderable + 'html
where
- 's: 'html,
- 'p: 'html,
+ 's: 'html,
+ 'p: 'html,
{
- maud_move!(
- div .wiki-main {
+ maud_move!(
+ div .wiki-main {
- // Slide in/out for mobile
- input #wiki-aside-shown type="checkbox" hidden;
+ // Slide in/out for mobile
+ input #wiki-aside-shown type="checkbox" hidden;
- aside .wiki-aside {
- // Slide button
- label .wiki-aside__slider for="wiki-aside-shown" {
- img .wiki-icon src="/static/svg/double-arrow.svg" width="24" height="24";
- }
- (crate::html::misc::show_outline(outline))
- }
+ aside .wiki-aside {
+ // Slide button
+ label .wiki-aside__slider for="wiki-aside-shown" {
+ img .wiki-icon src="/static/svg/double-arrow.svg" width="24" height="24";
+ }
+ (crate::html::misc::show_outline(outline))
+ }
- article .wiki-article /*class:list={classlist)*/ {
- header class="markdown" {
- h1 #top { (title) }
- }
- section .wiki-article__markdown.markdown {
- (Raw(parsed))
- }
+ article .wiki-article /*class:list={classlist)*/ {
+ header class="markdown" {
+ h1 #top { (title) }
+ }
+ section .wiki-article__markdown.markdown {
+ (Raw(parsed))
+ }
- @if let Some(bib) = bibliography.0 {
- (crate::html::misc::emit_bibliography(bib))
- }
- }
- }
- )
+ @if let Some(bib) = bibliography.0 {
+ (crate::html::misc::emit_bibliography(bib))
+ }
+ }
+ }
+ )
}
diff --git a/src/html/slideshow.rs b/src/html/slideshow.rs
index 49af0be..ffd46f6 100644
--- a/src/html/slideshow.rs
+++ b/src/html/slideshow.rs
@@ -1,6 +1,6 @@
-use camino::{Utf8Path, Utf8PathBuf};
+use camino::Utf8Path;
use chrono::{DateTime, Utc};
-use hauchiwa::{Bibliography, Link, LinkDate, Linkable, Outline, Sack};
+use hauchiwa::{Bibliography, Outline, Sack};
use hayagriva::Library;
use hypertext::{html_elements, maud, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
@@ -16,77 +16,66 @@ const CSS: &str = r#"
/// Represents a slideshow
#[derive(Deserialize, Debug, Clone)]
pub(crate) struct Slideshow {
- pub title: String,
- #[serde(with = "super::isodate")]
- pub date: DateTime,
- pub desc: Option,
+ pub title: String,
+ #[serde(with = "super::isodate")]
+ pub date: DateTime,
+ pub desc: Option,
}
pub fn parse_content(
- content: &str,
- sack: &Sack,
- path: &Utf8Path,
- library: Option<&Library>,
+ content: &str,
+ sack: &Sack,
+ path: &Utf8Path,
+ library: Option<&Library>,
) -> (String, Outline, Bibliography) {
- let parsed = content
- .split("\n-----\n")
- .map(|chunk| {
- chunk
- .split("\n---\n")
- .map(|slide| crate::text::md::parse(&slide, sack, path, library).0)
- .collect::>()
- })
- .map(|stack| match stack.len() > 1 {
- true => format!(
- "",
- stack
- .into_iter()
- .map(|slide| format!(""))
- .collect::()
- ),
- false => format!("", stack[0]),
- })
- .collect::();
- (parsed, Outline(vec![]), Bibliography(None))
+ let parsed = content
+ .split("\n-----\n")
+ .map(|chunk| {
+ chunk
+ .split("\n---\n")
+ .map(|slide| crate::text::md::parse(slide, sack, path, library).0)
+ .collect::>()
+ })
+ .map(|stack| match stack.len() > 1 {
+ true => format!(
+ "",
+ stack
+ .into_iter()
+ .map(|slide| format!(""))
+ .collect::()
+ ),
+ false => format!("", stack[0]),
+ })
+ .collect::();
+ (parsed, Outline(vec![]), Bibliography(None))
}
pub fn as_html(
- slides: &Slideshow,
- parsed: &str,
- sack: &Sack,
- _: Outline,
- _: Bibliography,
+ slides: &Slideshow,
+ parsed: &str,
+ sack: &Sack,
+ _: Outline,
+ _: Bibliography,
) -> String {
- show(slides, sack, parsed)
-}
-
-pub fn as_link(slides: &Slideshow, path: Utf8PathBuf) -> Option {
- Some(Linkable::Date(LinkDate {
- link: Link {
- path,
- name: slides.title.to_owned(),
- desc: slides.desc.to_owned(),
- },
- date: slides.date.to_owned(),
- }))
+ show(slides, sack, parsed)
}
pub fn show(fm: &Slideshow, sack: &Sack, slides: &str) -> String {
- crate::html::bare(
- sack,
- maud!(
- div .reveal {
- div .slides {
- (Raw(slides))
- }
- }
+ crate::html::bare(
+ sack,
+ maud!(
+ div .reveal {
+ div .slides {
+ (Raw(slides))
+ }
+ }
- style { (Raw(CSS)) }
- ),
- fm.title.clone(),
- Some(&["reveal".into()]),
- )
- .unwrap()
- .render()
- .into()
+ style { (Raw(CSS)) }
+ ),
+ fm.title.clone(),
+ Some(&["reveal".into()]),
+ )
+ .unwrap()
+ .render()
+ .into()
}
diff --git a/src/html/wiki.rs b/src/html/wiki.rs
index 6435ca5..ed6bdbd 100644
--- a/src/html/wiki.rs
+++ b/src/html/wiki.rs
@@ -1,5 +1,5 @@
-use camino::{Utf8Path, Utf8PathBuf};
-use hauchiwa::{Bibliography, Link, Linkable, Outline, Sack};
+use camino::Utf8Path;
+use hauchiwa::{Bibliography, Outline, Sack};
use hayagriva::Library;
use hypertext::{html_elements, maud_move, GlobalAttributes, Raw, Renderable};
use serde::Deserialize;
@@ -29,14 +29,6 @@ pub fn as_html(
wiki(meta, parsed, sack, outline, bibliography)
}
-pub fn as_link(meta: &Wiki, path: Utf8PathBuf) -> Option {
- Some(Linkable::Link(Link {
- path,
- name: meta.title.to_owned(),
- desc: None,
- }))
-}
-
fn wiki(
matter: &Wiki,
parsed: &str,
diff --git a/src/main.rs b/src/main.rs
index 56d9020..61173c5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,9 +2,10 @@ mod html;
mod text;
mod ts;
-use camino::Utf8Path;
+use camino::{Utf8Path, Utf8PathBuf};
+use chrono::{DateTime, Utc};
use clap::{Parser, ValueEnum};
-use hauchiwa::{Collection, Link, LinkDate, Processor, Website};
+use hauchiwa::{Collection, Processor, Website};
use html::{Post, Slideshow, Wiki};
use hypertext::Renderable;
@@ -20,6 +21,25 @@ enum Mode {
Watch,
}
+#[derive(Debug, Clone)]
+pub struct Link {
+ pub path: Utf8PathBuf,
+ pub name: String,
+ pub desc: Option,
+}
+
+#[derive(Debug, Clone)]
+pub struct LinkDate {
+ pub link: Link,
+ pub date: DateTime,
+}
+
+#[derive(Debug, Clone)]
+pub enum Linkable {
+ Link(Link),
+ Date(LinkDate),
+}
+
fn main() {
let args = Args::parse();
@@ -32,7 +52,6 @@ fn main() {
Processor {
read_content: crate::html::post::parse_content,
to_html: crate::html::post::as_html,
- to_link: crate::html::post::as_link,
},
),
Collection::glob_with::(
@@ -42,7 +61,6 @@ fn main() {
Processor {
read_content: crate::html::post::parse_content,
to_html: crate::html::post::as_html,
- to_link: crate::html::post::as_link,
},
),
Collection::glob_with::(
@@ -52,7 +70,6 @@ fn main() {
Processor {
read_content: crate::html::slideshow::parse_content,
to_html: crate::html::slideshow::as_html,
- to_link: crate::html::slideshow::as_link,
},
),
Collection::glob_with::(
@@ -62,7 +79,6 @@ fn main() {
Processor {
read_content: crate::html::wiki::parse_content,
to_html: crate::html::wiki::as_html,
- to_link: crate::html::wiki::as_link,
},
),
Collection::glob_with::(
@@ -72,7 +88,6 @@ fn main() {
Processor {
read_content: crate::html::post::parse_content,
to_html: crate::html::as_html,
- to_link: crate::html::post::as_link,
},
),
])
@@ -85,7 +100,7 @@ fn main() {
|sack| crate::html::map(sack).unwrap().render().to_owned().into(),
"map/index.html".into(),
)
- .add_virtual(|sack| crate::html::search(sack), "search/index.html".into())
+ .add_virtual(crate::html::search, "search/index.html".into())
.add_virtual(
|sack| {
crate::html::to_list(
diff --git a/src/text/md.rs b/src/text/md.rs
index 5a581a9..771c4f5 100644
--- a/src/text/md.rs
+++ b/src/text/md.rs
@@ -1,12 +1,12 @@
use std::collections::HashMap;
-use camino::{Utf8Path, Utf8PathBuf};
+use camino::Utf8Path;
use hauchiwa::{Bibliography, Outline, Sack};
use hayagriva::{
- archive::ArchivedStyle,
- citationberg::{IndependentStyle, Locale, Style},
- BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest,
- Library,
+ archive::ArchivedStyle,
+ citationberg::{IndependentStyle, Locale, Style},
+ BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest,
+ Library,
};
use hypertext::Renderable;
use once_cell::sync::Lazy;
@@ -16,369 +16,364 @@ use regex::Regex;
use crate::ts;
static OPTS: Lazy = Lazy::new(|| {
- Options::empty()
- .union(Options::ENABLE_MATH)
- .union(Options::ENABLE_TABLES)
- .union(Options::ENABLE_TASKLISTS)
- .union(Options::ENABLE_STRIKETHROUGH)
- .union(Options::ENABLE_SMART_PUNCTUATION)
+ Options::empty()
+ .union(Options::ENABLE_MATH)
+ .union(Options::ENABLE_TABLES)
+ .union(Options::ENABLE_TASKLISTS)
+ .union(Options::ENABLE_STRIKETHROUGH)
+ .union(Options::ENABLE_SMART_PUNCTUATION)
});
static KATEX_I: Lazy = Lazy::new(|| {
- katex::opts::Opts::builder()
- .output_type(katex::OutputType::Mathml)
- .build()
- .unwrap()
+ katex::opts::Opts::builder()
+ .output_type(katex::OutputType::Mathml)
+ .build()
+ .unwrap()
});
static KATEX_B: Lazy = Lazy::new(|| {
- katex::opts::Opts::builder()
- .output_type(katex::OutputType::Mathml)
- .display_mode(true)
- .build()
- .unwrap()
+ katex::opts::Opts::builder()
+ .output_type(katex::OutputType::Mathml)
+ .display_mode(true)
+ .build()
+ .unwrap()
});
static LOCALE: Lazy> = Lazy::new(hayagriva::archive::locales);
static STYLE: Lazy =
- Lazy::new(
- || match ArchivedStyle::InstituteOfElectricalAndElectronicsEngineers.get() {
- Style::Independent(style) => style,
- Style::Dependent(_) => unreachable!(),
- },
- );
+ Lazy::new(
+ || match ArchivedStyle::InstituteOfElectricalAndElectronicsEngineers.get() {
+ Style::Independent(style) => style,
+ Style::Dependent(_) => unreachable!(),
+ },
+ );
pub fn parse(
- content: &str,
- sack: &Sack,
- path: &Utf8Path,
- library: Option<&Library>,
+ content: &str,
+ sack: &Sack,
+ path: &Utf8Path,
+ library: Option<&Library>,
) -> (String, Outline, Bibliography) {
- let (outline, stream) = {
- let stream = Parser::new_ext(content, *OPTS);
- let mut stream: Vec<_> = TextMergeStream::new(stream).collect();
- let outline = set_heading_ids(&mut stream);
- (outline, stream)
- };
+ let (outline, stream) = {
+ let stream = Parser::new_ext(content, *OPTS);
+ let mut stream: Vec<_> = TextMergeStream::new(stream).collect();
+ let outline = set_heading_ids(&mut stream);
+ (outline, stream)
+ };
- let stream = stream
- .into_iter()
- .map(make_math)
- .map(make_emoji)
- .map(swap_hashed_image(path, sack))
- .collect::>();
+ let stream = stream
+ .into_iter()
+ .map(make_math)
+ .map(make_emoji)
+ .map(swap_hashed_image(path, sack))
+ .collect::>();
- let stream = make_code(stream)
- .into_iter()
- .flat_map(make_ruby)
- .flat_map(make_cite)
- .collect::>();
+ let stream = make_code(stream)
+ .into_iter()
+ .flat_map(make_ruby)
+ .flat_map(make_cite)
+ .collect::>();
- let (stream, bib) = match library {
- Some(lib) => make_bib(stream, lib),
- None => (stream, None),
- };
+ let (stream, bib) = match library {
+ Some(lib) => make_bib(stream, lib),
+ None => (stream, None),
+ };
- let mut parsed = String::new();
- pulldown_cmark::html::push_html(&mut parsed, stream.into_iter());
+ let mut parsed = String::new();
+ pulldown_cmark::html::push_html(&mut parsed, stream.into_iter());
- (parsed, outline, Bibliography(bib))
+ (parsed, outline, Bibliography(bib))
}
-fn make_bib<'a, 'b>(
- stream: Vec>,
- lib: &'b Library,
-) -> (Vec>, Option>) {
- let mut driver = BibliographyDriver::new();
+fn make_bib<'a>(stream: Vec>, lib: &Library) -> (Vec>, Option>) {
+ let mut driver = BibliographyDriver::new();
- for event in stream.iter() {
- match event {
- Event::InlineMath(ref text) => match lib.get(text) {
- Some(entry) => driver.citation(CitationRequest::from_items(
- vec![CitationItem::with_entry(entry)],
- &STYLE,
- &LOCALE,
- )),
- None => (),
- },
- _ => (),
- }
- }
+ for event in stream.iter() {
+ if let Event::InlineMath(ref text) = event {
+ if let Some(entry) = lib.get(text) {
+ driver.citation(CitationRequest::from_items(
+ vec![CitationItem::with_entry(entry)],
+ &STYLE,
+ &LOCALE,
+ ))
+ }
+ }
+ }
- // add fake citation to make all entries show up
- driver.citation(CitationRequest::from_items(
- lib.iter().map(CitationItem::with_entry).collect(),
- &STYLE,
- &LOCALE,
- ));
+ // add fake citation to make all entries show up
+ driver.citation(CitationRequest::from_items(
+ lib.iter().map(CitationItem::with_entry).collect(),
+ &STYLE,
+ &LOCALE,
+ ));
- let res = driver.finish(BibliographyRequest {
- style: &STYLE,
- locale: None,
- locale_files: &LOCALE,
- });
+ let res = driver.finish(BibliographyRequest {
+ style: &STYLE,
+ locale: None,
+ locale_files: &LOCALE,
+ });
- let mut n = 0;
- let stream = stream
- .into_iter()
- .map(|event| match event {
- Event::InlineMath(name) => {
- let mut buffer = String::from("");
- match res.citations.get(n) {
- Some(rf) => rf
- .citation
- .write_buf(&mut buffer, BufWriteFormat::Html)
- .unwrap(),
- None => buffer.push_str(&name),
- };
- buffer.push_str("");
- n += 1;
- Event::InlineHtml(buffer.into())
- }
- _ => event,
- })
- .collect();
+ let mut n = 0;
+ let stream = stream
+ .into_iter()
+ .map(|event| match event {
+ Event::InlineMath(name) => {
+ let mut buffer = String::from("");
+ match res.citations.get(n) {
+ Some(rf) => rf
+ .citation
+ .write_buf(&mut buffer, BufWriteFormat::Html)
+ .unwrap(),
+ None => buffer.push_str(&name),
+ };
+ buffer.push_str("");
+ n += 1;
+ Event::InlineHtml(buffer.into())
+ }
+ _ => event,
+ })
+ .collect();
- let bib = res.bibliography.map(|bib| {
- bib.items
- .iter()
- .map(|x| {
- let mut buffer = String::new();
- x.content
- .write_buf(&mut buffer, BufWriteFormat::Html)
- .unwrap();
- buffer
- })
- .collect::>()
- });
+ let bib = res.bibliography.map(|bib| {
+ bib.items
+ .iter()
+ .map(|x| {
+ let mut buffer = String::new();
+ x.content
+ .write_buf(&mut buffer, BufWriteFormat::Html)
+ .unwrap();
+ buffer
+ })
+ .collect::>()
+ });
- (stream, bib)
+ (stream, bib)
}
static RE_CITE: Lazy = Lazy::new(|| Regex::new(r":cite\[([^\]]+)\]").unwrap());
#[derive(Debug)]
enum Annotated_<'a> {
- Text(&'a str),
- Cite(&'a str),
+ Text(&'a str),
+ Cite(&'a str),
}
fn annotate_(input: &str) -> Vec {
- let mut parts: Vec = Vec::new();
- let mut last_index = 0;
+ let mut parts: Vec = Vec::new();
+ let mut last_index = 0;
- for cap in RE_CITE.captures_iter(input) {
- let cite = cap.get(1).unwrap().as_str();
- let index = cap.get(0).unwrap().start();
+ for cap in RE_CITE.captures_iter(input) {
+ let cite = cap.get(1).unwrap().as_str();
+ let index = cap.get(0).unwrap().start();
- if index > last_index {
- parts.push(Annotated_::Text(&input[last_index..index]));
- }
+ if index > last_index {
+ parts.push(Annotated_::Text(&input[last_index..index]));
+ }
- parts.push(Annotated_::Cite(cite));
- last_index = cap.get(0).unwrap().end();
- }
+ parts.push(Annotated_::Cite(cite));
+ last_index = cap.get(0).unwrap().end();
+ }
- if last_index < input.len() {
- parts.push(Annotated_::Text(&input[last_index..]));
- }
+ if last_index < input.len() {
+ parts.push(Annotated_::Text(&input[last_index..]));
+ }
- parts
+ parts
}
fn make_cite(event: Event) -> Vec {
- match event {
- Event::Text(ref text) => annotate_(text)
- .into_iter()
- .map(|e| match e {
- Annotated_::Text(text) => Event::Text(text.to_owned().into()),
- Annotated_::Cite(cite) => Event::InlineMath(cite.to_owned().into()),
- })
- .collect(),
- _ => vec![event],
- }
+ match event {
+ Event::Text(ref text) => annotate_(text)
+ .into_iter()
+ .map(|e| match e {
+ Annotated_::Text(text) => Event::Text(text.to_owned().into()),
+ Annotated_::Cite(cite) => Event::InlineMath(cite.to_owned().into()),
+ })
+ .collect(),
+ _ => vec![event],
+ }
}
fn set_heading_ids(events: &mut [Event]) -> Outline {
- let mut cnt = HashMap::::new();
- let mut out = Vec::new();
- let mut buf = String::new();
- let mut ptr = None;
+ let mut cnt = HashMap::::new();
+ let mut out = Vec::new();
+ let mut buf = String::new();
+ let mut ptr = None;
- for event in events {
- match event {
- Event::Start(ref mut tag @ Tag::Heading { .. }) => {
- ptr = Some(tag);
- }
- Event::Text(ref text) if ptr.is_some() => buf.push_str(text),
- Event::End(TagEnd::Heading(..)) => {
- let txt = std::mem::take(&mut buf);
- let url = txt.to_lowercase().replace(' ', "-");
- let url = match cnt.get_mut(&url) {
- Some(ptr) => {
- *ptr += 1;
- format!("{url}-{ptr}")
- }
- None => {
- cnt.insert(url.clone(), 0);
- url
- }
- };
- match ptr.take().unwrap() {
- Tag::Heading { ref mut id, .. } => *id = Some(url.clone().into()),
- _ => unreachable!(),
- }
- out.push((txt, url));
- }
- _ => (),
- }
- }
+ for event in events {
+ match event {
+ Event::Start(ref mut tag @ Tag::Heading { .. }) => {
+ ptr = Some(tag);
+ }
+ Event::Text(ref text) if ptr.is_some() => buf.push_str(text),
+ Event::End(TagEnd::Heading(..)) => {
+ let txt = std::mem::take(&mut buf);
+ let url = txt.to_lowercase().replace(' ', "-");
+ let url = match cnt.get_mut(&url) {
+ Some(ptr) => {
+ *ptr += 1;
+ format!("{url}-{ptr}")
+ }
+ None => {
+ cnt.insert(url.clone(), 0);
+ url
+ }
+ };
+ match ptr.take().unwrap() {
+ Tag::Heading { ref mut id, .. } => *id = Some(url.clone().into()),
+ _ => unreachable!(),
+ }
+ out.push((txt, url));
+ }
+ _ => (),
+ }
+ }
- Outline(out)
+ Outline(out)
}
fn make_math(event: Event) -> Event {
- match event {
- Event::InlineMath(math) => {
- Event::InlineHtml(katex::render_with_opts(&math, &*KATEX_I).unwrap().into())
- }
- Event::DisplayMath(math) => {
- Event::Html(katex::render_with_opts(&math, &*KATEX_B).unwrap().into())
- }
- _ => event,
- }
+ match event {
+ Event::InlineMath(math) => {
+ Event::InlineHtml(katex::render_with_opts(&math, &*KATEX_I).unwrap().into())
+ }
+ Event::DisplayMath(math) => {
+ Event::Html(katex::render_with_opts(&math, &*KATEX_B).unwrap().into())
+ }
+ _ => event,
+ }
}
fn make_code(es: Vec) -> Vec {
- let mut buff = Vec::new();
- let mut lang = None;
- let mut code = String::new();
+ let mut buff = Vec::new();
+ let mut lang = None;
+ let mut code = String::new();
- for event in es {
- match event {
- Event::Start(Tag::CodeBlock(kind)) => match kind {
- CodeBlockKind::Indented => (),
- CodeBlockKind::Fenced(name) => lang = Some(name),
- },
- Event::End(TagEnd::CodeBlock) => {
- let lang = lang.take().unwrap_or("".into());
- let html = ts::highlight(&lang, &code).render().as_str().to_owned();
- buff.push(Event::Html(html.into()));
- code.clear();
- }
- Event::Text(text) => match lang {
- None => buff.push(Event::Text(text)),
- Some(_) => code.push_str(&text),
- },
- _ => buff.push(event),
- }
- }
+ for event in es {
+ match event {
+ Event::Start(Tag::CodeBlock(kind)) => match kind {
+ CodeBlockKind::Indented => (),
+ CodeBlockKind::Fenced(name) => lang = Some(name),
+ },
+ Event::End(TagEnd::CodeBlock) => {
+ let lang = lang.take().unwrap_or("".into());
+ let html = ts::highlight(&lang, &code).render().as_str().to_owned();
+ buff.push(Event::Html(html.into()));
+ code.clear();
+ }
+ Event::Text(text) => match lang {
+ None => buff.push(Event::Text(text)),
+ Some(_) => code.push_str(&text),
+ },
+ _ => buff.push(event),
+ }
+ }
- buff
+ buff
}
static RE_RUBY: Lazy = Lazy::new(|| Regex::new(r"\[([^\]]+)\]\{([^}]+)\}").unwrap());
#[derive(Debug)]
enum Annotated<'a> {
- Text(&'a str),
- Ruby(&'a str, &'a str),
+ Text(&'a str),
+ Ruby(&'a str, &'a str),
}
fn annotate(input: &str) -> Vec {
- let mut parts: Vec = Vec::new();
- let mut last_index = 0;
+ let mut parts: Vec = Vec::new();
+ let mut last_index = 0;
- for cap in RE_RUBY.captures_iter(input) {
- let text = cap.get(1).unwrap().as_str();
- let ruby = cap.get(2).unwrap().as_str();
- let index = cap.get(0).unwrap().start();
+ for cap in RE_RUBY.captures_iter(input) {
+ let text = cap.get(1).unwrap().as_str();
+ let ruby = cap.get(2).unwrap().as_str();
+ let index = cap.get(0).unwrap().start();
- if index > last_index {
- parts.push(Annotated::Text(&input[last_index..index]));
- }
+ if index > last_index {
+ parts.push(Annotated::Text(&input[last_index..index]));
+ }
- parts.push(Annotated::Ruby(text, ruby));
- last_index = cap.get(0).unwrap().end();
- }
+ parts.push(Annotated::Ruby(text, ruby));
+ last_index = cap.get(0).unwrap().end();
+ }
- if last_index < input.len() {
- parts.push(Annotated::Text(&input[last_index..]));
- }
+ if last_index < input.len() {
+ parts.push(Annotated::Text(&input[last_index..]));
+ }
- parts
+ parts
}
fn make_ruby(event: Event) -> Vec {
- match event {
- Event::Text(ref text) => annotate(text)
- .into_iter()
- .map(|el| match el {
- Annotated::Text(text) => Event::Text(text.to_owned().into()),
- Annotated::Ruby(t, f) => Event::InlineHtml(
- format!("{t}").into(),
- ),
- })
- .collect(),
- _ => vec![event],
- }
+ match event {
+ Event::Text(ref text) => annotate(text)
+ .into_iter()
+ .map(|el| match el {
+ Annotated::Text(text) => Event::Text(text.to_owned().into()),
+ Annotated::Ruby(t, f) => Event::InlineHtml(
+ format!("{t}").into(),
+ ),
+ })
+ .collect(),
+ _ => vec![event],
+ }
}
fn make_emoji(event: Event) -> Event {
- match event {
- Event::Text(ref text) => {
- let mut buf = None;
- let mut top = 0;
- let mut old = 0;
+ match event {
+ Event::Text(ref text) => {
+ let mut buf = None;
+ let mut top = 0;
+ let mut old = 0;
- for (idx, _) in text.match_indices(':') {
- let key = &text[old..idx];
+ for (idx, _) in text.match_indices(':') {
+ let key = &text[old..idx];
- if let Some(emoji) = emojis::get_by_shortcode(key) {
- let buf = buf.get_or_insert_with(|| String::with_capacity(text.len()));
- buf.push_str(&text[top..old - 1]);
- buf.push_str(emoji.as_str());
- top = idx + 1;
- }
+ if let Some(emoji) = emojis::get_by_shortcode(key) {
+ let buf = buf.get_or_insert_with(|| String::with_capacity(text.len()));
+ buf.push_str(&text[top..old - 1]);
+ buf.push_str(emoji.as_str());
+ top = idx + 1;
+ }
- old = idx + 1;
- }
+ old = idx + 1;
+ }
- if let Some(ref mut buf) = buf {
- buf.push_str(&text[top..]);
- }
+ if let Some(ref mut buf) = buf {
+ buf.push_str(&text[top..]);
+ }
- match buf {
- None => event,
- Some(buf) => Event::Text(buf.into()),
- }
- }
- _ => event,
- }
+ match buf {
+ None => event,
+ Some(buf) => Event::Text(buf.into()),
+ }
+ }
+ _ => event,
+ }
}
fn swap_hashed_image<'a>(dir: &'a Utf8Path, sack: &'a Sack) -> impl Fn(Event) -> Event + 'a {
- move |event| match event {
- Event::Start(start) => match start {
- Tag::Image {
- dest_url,
- link_type,
- title,
- id,
- } => {
- let rel = dir.join(dest_url.as_ref());
- let img = sack.get_image(&rel);
- let hashed = img.map(|path| path.as_str().to_owned().into());
- Event::Start(Tag::Image {
- link_type,
- dest_url: hashed.unwrap_or(dest_url),
- title,
- id,
- })
- }
- _ => Event::Start(start),
- },
- _ => event,
- }
+ move |event| match event {
+ Event::Start(start) => match start {
+ Tag::Image {
+ dest_url,
+ link_type,
+ title,
+ id,
+ } => {
+ let rel = dir.join(dest_url.as_ref());
+ let img = sack.get_image(&rel);
+ let hashed = img.map(|path| path.as_str().to_owned().into());
+ Event::Start(Tag::Image {
+ link_type,
+ dest_url: hashed.unwrap_or(dest_url),
+ title,
+ id,
+ })
+ }
+ _ => Event::Start(start),
+ },
+ _ => event,
+ }
}