render bibliography
This commit is contained in:
parent
115613071c
commit
d87069c17d
|
@ -15,17 +15,3 @@ I've come across 〜達 used for inanimate things several times with one example
|
||||||
奈落への滝が嗤い続け轟く
|
奈落への滝が嗤い続け轟く
|
||||||
“目指したトコロは此処だったのか?”
|
“目指したトコロは此処だったのか?”
|
||||||
今は先を急ぐ **水達**に乗せられたまま
|
今は先を急ぐ **水達**に乗せられたまま
|
||||||
|
|
||||||
|
|
||||||
## Bibliography
|
|
||||||
|
|
||||||
:::bibtex
|
|
||||||
@book{dojg-advanced,
|
|
||||||
title = {A dictionary of advanced Japanese grammar},
|
|
||||||
author = {Makino, Seiichi and Tsutsui, Michio},
|
|
||||||
isbn = {9784789012959},
|
|
||||||
lccn = {2017414531},
|
|
||||||
year = {2008},
|
|
||||||
publisher = {Japan Times}
|
|
||||||
}
|
|
||||||
:::
|
|
8
content/wiki/japanese/tachi/ref.bib
Normal file
8
content/wiki/japanese/tachi/ref.bib
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
@book{dojg-advanced,
|
||||||
|
title = {A dictionary of advanced Japanese grammar},
|
||||||
|
author = {Makino, Seiichi and Tsutsui, Michio},
|
||||||
|
isbn = {9784789012959},
|
||||||
|
lccn = {2017414531},
|
||||||
|
year = {2008},
|
||||||
|
publisher = {Japan Times}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ mod render;
|
||||||
mod sack;
|
mod sack;
|
||||||
|
|
||||||
use camino::Utf8PathBuf;
|
use camino::Utf8PathBuf;
|
||||||
|
use hayagriva::Library;
|
||||||
use hypertext::Renderable;
|
use hypertext::Renderable;
|
||||||
|
|
||||||
pub use load::{gather, Source, SourceKind};
|
pub use load::{gather, Source, SourceKind};
|
||||||
|
@ -19,6 +20,7 @@ pub trait Content {
|
||||||
content: T,
|
content: T,
|
||||||
outline: Outline,
|
outline: Outline,
|
||||||
sack: &'s Sack,
|
sack: &'s Sack,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'html
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
'f: 'html,
|
'f: 'html,
|
||||||
|
@ -28,5 +30,5 @@ pub trait Content {
|
||||||
|
|
||||||
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable>;
|
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable>;
|
||||||
|
|
||||||
fn render(data: &str) -> (Outline, String);
|
fn render(data: &str, lib: Option<&Library>) -> (Outline, String, Option<Vec<String>>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,10 @@ pub fn render(items: &[Item]) {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let sack = Sack::new(&assets);
|
|
||||||
|
|
||||||
for item in items {
|
for item in items {
|
||||||
match item {
|
match item {
|
||||||
Item::Real(real) => render_real(real, &sack),
|
Item::Real(real) => render_real(real, &Sack::new(&assets, &real.out)),
|
||||||
Item::Fake(fake) => render_fake(fake, &sack),
|
Item::Fake(fake) => render_fake(fake, &Sack::new(&assets, &fake.0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use camino::Utf8PathBuf;
|
||||||
|
use hayagriva::Library;
|
||||||
|
|
||||||
use crate::html::{Link, LinkDate, Linkable};
|
use crate::html::{Link, LinkDate, Linkable};
|
||||||
|
|
||||||
use super::Asset;
|
use super::{Asset, AssetKind};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -35,11 +38,12 @@ impl TreePage {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Sack<'a> {
|
pub struct Sack<'a> {
|
||||||
assets: &'a [&'a Asset],
|
assets: &'a [&'a Asset],
|
||||||
|
path: &'a Utf8PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Sack<'a> {
|
impl<'a> Sack<'a> {
|
||||||
pub fn new(assets: &'a [&'a Asset]) -> Self {
|
pub fn new(assets: &'a [&'a Asset], path: &'a Utf8PathBuf) -> Self {
|
||||||
Self { assets }
|
Self { assets, path }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_links(&self, path: &str) -> Vec<LinkDate> {
|
pub fn get_links(&self, path: &str) -> Vec<LinkDate> {
|
||||||
|
@ -69,4 +73,21 @@ impl<'a> Sack<'a> {
|
||||||
|
|
||||||
tree
|
tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_library(&self) -> Option<&Library> {
|
||||||
|
let glob = format!("{}/*.bib", self.path.parent()?);
|
||||||
|
let glob = glob::Pattern::new(&glob).unwrap();
|
||||||
|
let opts = glob::MatchOptions {
|
||||||
|
case_sensitive: true,
|
||||||
|
require_literal_separator: true,
|
||||||
|
require_literal_leading_dot: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.assets.iter()
|
||||||
|
.filter(|asset| glob.matches_path_with(asset.out.as_ref(), opts))
|
||||||
|
.find_map(|asset| match asset.kind {
|
||||||
|
AssetKind::Bib(ref lib) => Some(lib),
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ mod list;
|
||||||
mod show;
|
mod show;
|
||||||
mod special;
|
mod special;
|
||||||
mod wiki;
|
mod wiki;
|
||||||
|
mod misc;
|
||||||
|
|
||||||
pub use home::home;
|
pub use home::home;
|
||||||
pub use page::page;
|
pub use page::page;
|
||||||
|
|
|
@ -19,7 +19,7 @@ const INTRO: &str = r#"
|
||||||
|
|
||||||
|
|
||||||
fn intro() -> impl Renderable {
|
fn intro() -> impl Renderable {
|
||||||
let (_, html) = parse(INTRO);
|
let (_, html, _) = parse(INTRO, None);
|
||||||
maud!(
|
maud!(
|
||||||
section .p-card.intro-jp lang="ja-JP" {
|
section .p-card.intro-jp lang="ja-JP" {
|
||||||
(Raw(html))
|
(Raw(html))
|
||||||
|
|
95
src/html/misc.rs
Normal file
95
src/html/misc.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
|
||||||
|
|
||||||
|
use crate::gen::{Sack, TreePage};
|
||||||
|
use crate::text::md::Outline;
|
||||||
|
|
||||||
|
|
||||||
|
/// Render the outline for a document
|
||||||
|
pub fn show_outline(outline: Outline) -> impl Renderable {
|
||||||
|
maud_move!(
|
||||||
|
section .link-tree {
|
||||||
|
h2 .link-tree__heading {
|
||||||
|
a .link-tree__heading-text href="#top" { "Content" }
|
||||||
|
}
|
||||||
|
nav #table-of-contents .link-tree__nav {
|
||||||
|
ul .link-tree__nav-list {
|
||||||
|
@for (title, id) in outline.0 {
|
||||||
|
li .link-tree__nav-list-item {
|
||||||
|
a .link-tree__nav-list-text.link href=(format!("#{}", id)) {
|
||||||
|
(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the bibliography for a document
|
||||||
|
pub fn show_bibliography(bib: Vec<String>) -> impl Renderable {
|
||||||
|
maud_move!(
|
||||||
|
section .markdown {
|
||||||
|
h2 {
|
||||||
|
"Bibliography"
|
||||||
|
}
|
||||||
|
ol .bibliography {
|
||||||
|
@for item in bib {
|
||||||
|
li {
|
||||||
|
(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render the page tree
|
||||||
|
pub fn show_page_tree(sack: &Sack, glob: &str) -> impl Renderable {
|
||||||
|
let tree = sack.get_tree(glob);
|
||||||
|
|
||||||
|
maud_move!(
|
||||||
|
h2 .link-tree__heading {
|
||||||
|
// {pages.chain(x => x.prefix)
|
||||||
|
// .map(pathify)
|
||||||
|
// .mapOrDefault(href =>
|
||||||
|
// <a class="link-tree__heading-text" href={href}>{heading}</a>,
|
||||||
|
// <span class="link-tree__heading-text">{heading}</span>
|
||||||
|
// )}
|
||||||
|
}
|
||||||
|
nav .link-tree__nav {
|
||||||
|
(show_page_tree_level(&tree))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_page_tree_level(tree: &TreePage) -> impl Renderable + '_ {
|
||||||
|
let subs = {
|
||||||
|
let mut subs: Vec<_> = tree.subs.iter().collect();
|
||||||
|
subs.sort_by(|a, b| a.0.cmp(b.0));
|
||||||
|
subs
|
||||||
|
};
|
||||||
|
|
||||||
|
maud_move!(
|
||||||
|
ul .link-tree__nav-list {
|
||||||
|
@for (key, next) in subs {
|
||||||
|
li .link-tree__nav-list-item {
|
||||||
|
span .link-tree__nav-list-text {
|
||||||
|
@if let Some(ref link) = next.link {
|
||||||
|
a .link-tree__nav-list-text.link href=(link.path.as_str()) {
|
||||||
|
(&link.name)
|
||||||
|
}
|
||||||
|
} @else {
|
||||||
|
span .link-tree__nav-list-text {
|
||||||
|
(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@if !next.subs.is_empty() {
|
||||||
|
(show_page_tree_level(next))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,35 +1,16 @@
|
||||||
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
|
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
|
||||||
use crate::md::Post;
|
|
||||||
|
use crate::html::misc::{show_bibliography, show_outline};
|
||||||
use crate::html::page;
|
use crate::html::page;
|
||||||
|
use crate::md::Post;
|
||||||
use crate::text::md::Outline;
|
use crate::text::md::Outline;
|
||||||
|
|
||||||
|
|
||||||
pub fn tree(outline: Outline) -> impl Renderable {
|
|
||||||
maud_move!(
|
|
||||||
section .link-tree {
|
|
||||||
h2 .link-tree__heading {
|
|
||||||
a .link-tree__heading-text href="#top" { "Content" }
|
|
||||||
}
|
|
||||||
nav #table-of-contents .link-tree__nav {
|
|
||||||
ul .link-tree__nav-list {
|
|
||||||
@for (title, id) in outline.0 {
|
|
||||||
li .link-tree__nav-list-item {
|
|
||||||
a .link-tree__nav-list-text.link href=(format!("#{id}")) {
|
|
||||||
(title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn post<'fm, 'md, 'post, T>(
|
pub fn post<'fm, 'md, 'post, T>(
|
||||||
fm: &'fm Post,
|
fm: &'fm Post,
|
||||||
content: T,
|
content: T,
|
||||||
outline: Outline,
|
outline: Outline,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'post
|
) -> impl Renderable + 'post
|
||||||
where
|
where
|
||||||
'fm: 'post,
|
'fm: 'post,
|
||||||
|
@ -47,7 +28,7 @@ pub fn post<'fm, 'md, 'post, T>(
|
||||||
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";
|
||||||
}
|
}
|
||||||
(tree(outline))
|
(show_outline(outline))
|
||||||
}
|
}
|
||||||
|
|
||||||
article .wiki-article /*class:list={classlist)*/ {
|
article .wiki-article /*class:list={classlist)*/ {
|
||||||
|
@ -57,6 +38,10 @@ pub fn post<'fm, 'md, 'post, T>(
|
||||||
section .wiki-article__markdown.markdown {
|
section .wiki-article__markdown.markdown {
|
||||||
(content)
|
(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if let Some(bib) = bib {
|
||||||
|
(show_bibliography(bib))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,62 +1,10 @@
|
||||||
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
|
use hypertext::{html_elements, maud_move, GlobalAttributes, Renderable};
|
||||||
|
|
||||||
use crate::{
|
use crate::gen::Sack;
|
||||||
gen::{Sack, TreePage},
|
use crate::html::misc::show_page_tree;
|
||||||
html::page,
|
use crate::html::{misc::show_bibliography, page};
|
||||||
md::Wiki,
|
use crate::md::Wiki;
|
||||||
text::md::Outline
|
use crate::text::md::Outline;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn tree(sack: &Sack) -> impl Renderable {
|
|
||||||
let tree = sack.get_tree("wiki/**/*.html");
|
|
||||||
|
|
||||||
maud_move!(
|
|
||||||
h2 .link-tree__heading {
|
|
||||||
// {pages.chain(x => x.prefix)
|
|
||||||
// .map(pathify)
|
|
||||||
// .mapOrDefault(href =>
|
|
||||||
// <a class="link-tree__heading-text" href={href}>{heading}</a>,
|
|
||||||
// <span class="link-tree__heading-text">{heading}</span>
|
|
||||||
// )}
|
|
||||||
}
|
|
||||||
nav .link-tree__nav {
|
|
||||||
(list(&tree))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn list(tree: &TreePage) -> impl Renderable + '_ {
|
|
||||||
let subs = {
|
|
||||||
let mut subs: Vec<_> = tree.subs.iter().collect();
|
|
||||||
subs.sort_by(|a, b| a.0.cmp(b.0));
|
|
||||||
subs
|
|
||||||
};
|
|
||||||
|
|
||||||
maud_move!(
|
|
||||||
ul .link-tree__nav-list {
|
|
||||||
@for (key, next) in subs {
|
|
||||||
li .link-tree__nav-list-item {
|
|
||||||
span .link-tree__nav-list-text {
|
|
||||||
@if let Some(ref link) = next.link {
|
|
||||||
a .link-tree__nav-list-text.link href=(link.path.as_str()) {
|
|
||||||
(&link.name)
|
|
||||||
}
|
|
||||||
} @else {
|
|
||||||
span .link-tree__nav-list-text {
|
|
||||||
(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@if !next.subs.is_empty() {
|
|
||||||
(list(next))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn wiki<'data, 'html, 'sack, T>(
|
pub fn wiki<'data, 'html, 'sack, T>(
|
||||||
|
@ -64,6 +12,7 @@ pub fn wiki<'data, 'html, 'sack, T>(
|
||||||
content: T,
|
content: T,
|
||||||
_: Outline,
|
_: Outline,
|
||||||
sack: &'sack Sack,
|
sack: &'sack Sack,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'html
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
'sack: 'html,
|
'sack: 'html,
|
||||||
|
@ -84,7 +33,7 @@ pub fn wiki<'data, 'html, 'sack, T>(
|
||||||
// Navigation tree
|
// Navigation tree
|
||||||
section .link-tree {
|
section .link-tree {
|
||||||
div {
|
div {
|
||||||
(tree(sack))
|
(show_page_tree(sack, "wiki/**/*.html"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +45,10 @@ pub fn wiki<'data, 'html, 'sack, T>(
|
||||||
section .wiki-article__markdown.markdown {
|
section .wiki-article__markdown.markdown {
|
||||||
(content)
|
(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if let Some(bib) = bib {
|
||||||
|
(show_bibliography(bib))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -5,6 +5,7 @@ use std::fs;
|
||||||
use camino::{Utf8Path, Utf8PathBuf};
|
use camino::{Utf8Path, Utf8PathBuf};
|
||||||
use chrono::Datelike;
|
use chrono::Datelike;
|
||||||
use gen::{Asset, Sack, Content};
|
use gen::{Asset, Sack, Content};
|
||||||
|
use hayagriva::Library;
|
||||||
use html::{Link, LinkDate, Linkable};
|
use html::{Link, LinkDate, Linkable};
|
||||||
use hypertext::{Raw, Renderable};
|
use hypertext::{Raw, Renderable};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
@ -54,13 +55,14 @@ impl Content for md::Post {
|
||||||
content: T,
|
content: T,
|
||||||
outline: Outline,
|
outline: Outline,
|
||||||
_: &'s Sack,
|
_: &'s Sack,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'html
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
'f: 'html,
|
'f: 'html,
|
||||||
'm: 'html,
|
'm: 'html,
|
||||||
's: 'html,
|
's: 'html,
|
||||||
T: Renderable + 'm {
|
T: Renderable + 'm {
|
||||||
html::post(self, content, outline)
|
html::post(self, content, outline, bib)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
|
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
|
||||||
|
@ -74,8 +76,8 @@ impl Content for md::Post {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(data: &str) -> (Outline, String) {
|
fn render(data: &str, lib: Option<&Library>) -> (Outline, String, Option<Vec<String>>) {
|
||||||
text::md::parse(data)
|
text::md::parse(data, lib)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +87,7 @@ impl Content for md::Slide {
|
||||||
content: T,
|
content: T,
|
||||||
_: Outline,
|
_: Outline,
|
||||||
_: &'s Sack,
|
_: &'s Sack,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'html
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
'f: 'html,
|
'f: 'html,
|
||||||
|
@ -105,16 +108,16 @@ impl Content for md::Slide {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(data: &str) -> (Outline, String) {
|
fn render(data: &str, _: Option<&Library>) -> (Outline, String, Option<Vec<String>>) {
|
||||||
let html = data
|
let html = data
|
||||||
.split("\n-----\n")
|
.split("\n-----\n")
|
||||||
.map(|chunk| chunk.split("\n---\n").map(text::md::parse).map(|e| e.1).collect::<Vec<_>>())
|
.map(|chunk| chunk.split("\n---\n").map(|s| text::md::parse(s, None)).map(|e| e.1).collect::<Vec<_>>())
|
||||||
.map(|stack| match stack.len() > 1 {
|
.map(|stack| match stack.len() > 1 {
|
||||||
true => format!("<section>{}</section>", stack.into_iter().map(|slide| format!("<section>{slide}</section>")).collect::<String>()),
|
true => format!("<section>{}</section>", stack.into_iter().map(|slide| format!("<section>{slide}</section>")).collect::<String>()),
|
||||||
false => format!("<section>{}</section>", stack[0])
|
false => format!("<section>{}</section>", stack[0])
|
||||||
})
|
})
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
(Outline(vec![]), html)
|
(Outline(vec![]), html, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,13 +127,14 @@ impl Content for md::Wiki {
|
||||||
content: T,
|
content: T,
|
||||||
outline: Outline,
|
outline: Outline,
|
||||||
sack: &'s Sack,
|
sack: &'s Sack,
|
||||||
|
bib: Option<Vec<String>>,
|
||||||
) -> impl Renderable + 'html
|
) -> impl Renderable + 'html
|
||||||
where
|
where
|
||||||
'f: 'html,
|
'f: 'html,
|
||||||
'm: 'html,
|
'm: 'html,
|
||||||
's: 'html,
|
's: 'html,
|
||||||
T: Renderable + 'm {
|
T: Renderable + 'm {
|
||||||
html::wiki(self, content, outline, sack)
|
html::wiki(self, content, outline, sack, bib)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
|
fn as_link(&self, path: Utf8PathBuf) -> Option<Linkable> {
|
||||||
|
@ -141,8 +145,8 @@ impl Content for md::Wiki {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(data: &str) -> (Outline, String) {
|
fn render(data: &str, lib: Option<&Library>) -> (Outline, String, Option<Vec<String>>) {
|
||||||
text::md::parse(data)
|
text::md::parse(data, lib)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,8 +189,9 @@ fn transform<T>(meta: gen::Source) -> Asset
|
||||||
let link = T::as_link(&fm, Utf8Path::new("/").join(dir));
|
let link = T::as_link(&fm, Utf8Path::new("/").join(dir));
|
||||||
|
|
||||||
let call = move |sack: &Sack| {
|
let call = move |sack: &Sack| {
|
||||||
let (outline, html) = T::render(&md);
|
let lib = sack.get_library();
|
||||||
T::transform(&fm, Raw(html), outline, sack).render().into()
|
let (outline, html, bib) = T::render(&md, lib);
|
||||||
|
T::transform(&fm, Raw(html), outline, sack, bib).render().into()
|
||||||
};
|
};
|
||||||
|
|
||||||
gen::Asset {
|
gen::Asset {
|
||||||
|
@ -249,7 +254,7 @@ fn main() {
|
||||||
gen::Asset {
|
gen::Asset {
|
||||||
kind: gen::AssetKind::Html(Box::new(|_| {
|
kind: gen::AssetKind::Html(Box::new(|_| {
|
||||||
let data = std::fs::read_to_string("content/index.md").unwrap();
|
let data = std::fs::read_to_string("content/index.md").unwrap();
|
||||||
let (_, html) = text::md::parse(&data);
|
let (_, html, bib) = text::md::parse(&data, None);
|
||||||
html::home(Raw(html)).render().to_owned().into()
|
html::home(Raw(html)).render().to_owned().into()
|
||||||
})),
|
})),
|
||||||
out: "index.html".into(),
|
out: "index.html".into(),
|
||||||
|
|
117
src/text/md.rs
117
src/text/md.rs
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use hayagriva::{archive::ArchivedStyle, citationberg::{IndependentStyle, Locale, Style}, BibliographyDriver, BibliographyRequest, CitationItem, CitationRequest, Library};
|
||||||
use hypertext::Renderable;
|
use hypertext::Renderable;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag, TagEnd, TextMergeStream};
|
use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag, TagEnd, TextMergeStream};
|
||||||
|
@ -32,10 +33,19 @@ static KATEX_B: Lazy<katex::Opts> = Lazy::new(||
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static LOCALE: Lazy<Vec<Locale>> = Lazy::new(|| hayagriva::archive::locales());
|
||||||
|
|
||||||
|
static STYLE: Lazy<IndependentStyle> = Lazy::new(||
|
||||||
|
match ArchivedStyle::InstituteOfPhysicsNumeric.get() {
|
||||||
|
Style::Independent(style) => style,
|
||||||
|
Style::Dependent(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
pub struct Outline(pub Vec<(String, String)>);
|
pub struct Outline(pub Vec<(String, String)>);
|
||||||
|
|
||||||
|
|
||||||
pub fn parse(text: &str) -> (Outline, String) {
|
pub fn parse(text: &str, lib: Option<&Library>) -> (Outline, String, Option<Vec<String>>) {
|
||||||
let (outline, stream) = {
|
let (outline, stream) = {
|
||||||
let stream = Parser::new_ext(text, *OPTS);
|
let stream = Parser::new_ext(text, *OPTS);
|
||||||
let mut stream: Vec<_> = TextMergeStream::new(stream).collect();
|
let mut stream: Vec<_> = TextMergeStream::new(stream).collect();
|
||||||
|
@ -50,12 +60,113 @@ pub fn parse(text: &str) -> (Outline, String) {
|
||||||
|
|
||||||
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)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let (stream, bib) = match lib {
|
||||||
|
Some(lib) => make_bib(stream, lib),
|
||||||
|
None => (stream, None),
|
||||||
|
};
|
||||||
|
|
||||||
let mut html = String::new();
|
let mut html = String::new();
|
||||||
pulldown_cmark::html::push_html(&mut html, stream.into_iter());
|
pulldown_cmark::html::push_html(&mut html, stream.into_iter());
|
||||||
|
|
||||||
(outline, html)
|
(outline, html, bib)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_bib<'a, 'b>(stream: Vec<Event<'a>>, lib: &'b Library) -> (Vec<Event<'a>>, Option<Vec<String>>) {
|
||||||
|
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 => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(_) => {
|
||||||
|
let rf = match res.citations.get(n) {
|
||||||
|
Some(rf) => rf,
|
||||||
|
None => return event,
|
||||||
|
};
|
||||||
|
let rf = rf.citation.to_string().replace("\u{1b}[0m", "");
|
||||||
|
let rf = format!("<cite>{}</cite>", rf);
|
||||||
|
n += 1;
|
||||||
|
Event::InlineHtml(rf.into())
|
||||||
|
},
|
||||||
|
_ => event
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let bib = match res.bibliography {
|
||||||
|
Some(ref bib) => {
|
||||||
|
let test = bib.items.iter()
|
||||||
|
.map(|x| x.content.to_string()
|
||||||
|
.replace("\u{1b}[0m", "")
|
||||||
|
.replace("\u{01b}[3mA", "")
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
Some(test)
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
(stream, bib)
|
||||||
|
}
|
||||||
|
|
||||||
|
static RE_CITE: Lazy<Regex> = Lazy::new(|| Regex::new(r":cite\[([^\]]+)\]").unwrap());
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Annotated_<'a> {
|
||||||
|
Text(&'a str),
|
||||||
|
Cite(&'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn annotate_(input: &str) -> Vec<Annotated_> {
|
||||||
|
let mut parts: Vec<Annotated_> = 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();
|
||||||
|
|
||||||
|
if index > last_index {
|
||||||
|
parts.push(Annotated_::Text(&input[last_index..index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(Annotated_::Cite(cite));
|
||||||
|
last_index = cap.get(0).unwrap().end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if last_index < input.len() {
|
||||||
|
parts.push(Annotated_::Text(&input[last_index..]));
|
||||||
|
}
|
||||||
|
|
||||||
|
parts
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_cite(event: Event) -> 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 {
|
fn set_heading_ids(events: &mut [Event]) -> Outline {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
.csl-bib-body {
|
.bibliography {
|
||||||
display: flex;
|
li {
|
||||||
flex-direction: column;
|
padding-left: 0.7em;
|
||||||
gap: 0.5em;
|
|
||||||
|
&::marker {
|
||||||
|
content: '[' counter(list-item) ']';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue