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