Replace bibliography handling with bibliographix

Signed-off-by: trivernis <trivernis@protonmail.com>
feature/epub-rendering
trivernis 4 years ago
parent 53123705ac
commit 801268b804
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

36
Cargo.lock generated

@ -52,6 +52,15 @@ name = "base64"
version = "0.12.3" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bibliographix"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono-english 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "1.3.1" version = "1.3.1"
@ -98,7 +107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.13" version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
@ -106,6 +115,16 @@ dependencies = [
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "chrono-english"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"scanlex 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.33.2" version = "2.33.2"
@ -843,7 +862,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"line-wrap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "line-wrap 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1034,6 +1053,11 @@ dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "scanlex"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "schannel" name = "schannel"
version = "0.1.19" version = "0.1.19"
@ -1121,8 +1145,9 @@ version = "0.23.0"
dependencies = [ dependencies = [
"asciimath-rs 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "asciimath-rs 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bibliographix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"charred 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "charred 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gh-emoji 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "gh-emoji 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1563,6 +1588,7 @@ dependencies = [
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" "checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
"checksum bibliographix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba3bc8793948a3de7d106d5f855afb085b998585c5f407ae59cd5489d3ed97c8"
"checksum bincode 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" "checksum bincode 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" "checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
@ -1571,7 +1597,8 @@ dependencies = [
"checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518" "checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum charred 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e01302bf6a3d92a90baa965f84a735938520ab9fd896f0694a71e8dec5405ce" "checksum charred 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e01302bf6a3d92a90baa965f84a735938520ab9fd896f0694a71e8dec5405ce"
"checksum chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" "checksum chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
"checksum chrono-english 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4233ee19352739cfdcb5d7c2085005b166f6170ef2845ed9eef27a8fa5f95206"
"checksum clap 2.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "10040cdf04294b565d9e0319955430099ec3813a64c952b86a41200ad714ae48" "checksum clap 2.33.2 (registry+https://github.com/rust-lang/crates.io-index)" = "10040cdf04294b565d9e0319955430099ec3813a64c952b86a41200ad714ae48"
"checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59" "checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
@ -1678,6 +1705,7 @@ dependencies = [
"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" "checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
"checksum scanlex 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e6a2c84b697bc9496978f7457b17039a22b5d89c674964e8a480de4d5ddd55dc"
"checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" "checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" "checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"

@ -18,6 +18,8 @@ path = "src/main.rs"
[dependencies] [dependencies]
charred = "0.3.3" charred = "0.3.3"
asciimath-rs = "0.5.7"
bibliographix = "0.2.0"
crossbeam-utils = "0.7.2" crossbeam-utils = "0.7.2"
structopt = "0.3.14" structopt = "0.3.14"
minify = "1.1.1" minify = "1.1.1"
@ -32,9 +34,8 @@ notify = "4.0.12"
toml = "0.5.6" toml = "0.5.6"
serde ="1.0.111" serde ="1.0.111"
serde_derive = "1.0.111" serde_derive = "1.0.111"
asciimath-rs = "0.5.7"
reqwest = {version = "0.10", features=["blocking"]} reqwest = {version = "0.10", features=["blocking"]}
mime_guess = "2.0.3" mime_guess = "2.0.3"
mime = "0.3.16" mime = "0.3.16"
base64 = "0.12.3" base64 = "0.12.3"
rayon = "1.3.1" rayon = "1.3.1"

@ -1,15 +1,18 @@
pub mod tokens; pub mod tokens;
use crate::references::bibliography::{BibEntry, BibReference, Bibliography}; use crate::format::PlaceholderTemplate;
use crate::references::configuration::Configuration; use crate::references::configuration::{ConfigRefEntry, Configuration};
use crate::references::placeholders::ProcessPlaceholders; use crate::references::placeholders::ProcessPlaceholders;
use crate::references::templates::{Template, TemplateVariable}; use crate::references::templates::{Template, TemplateVariable};
use asciimath_rs::elements::special::Expression; use asciimath_rs::elements::special::Expression;
use bibliographix::bib_manager::BibManager;
use bibliographix::bibliography::bibliography_entry::BibliographyEntryReference;
use bibliographix::references::bib_reference::BibRefAnchor;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::read; use std::fs::read;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, Mutex, RwLock};
pub const SECTION: &str = "section"; pub const SECTION: &str = "section";
pub const PARAGRAPH: &str = "paragraph"; pub const PARAGRAPH: &str = "paragraph";
@ -56,7 +59,7 @@ pub enum Line {
Ruler(Ruler), Ruler(Ruler),
Anchor(Anchor), Anchor(Anchor),
Centered(Centered), Centered(Centered),
BibEntry(Arc<RwLock<BibEntry>>), BibEntry(BibEntry),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -66,7 +69,7 @@ pub struct Document {
pub(crate) path: Option<String>, pub(crate) path: Option<String>,
pub(crate) placeholders: Vec<Arc<RwLock<Placeholder>>>, pub(crate) placeholders: Vec<Arc<RwLock<Placeholder>>>,
pub config: Configuration, pub config: Configuration,
pub bibliography: Bibliography, pub bibliography: BibManager,
pub stylesheets: Vec<String>, pub stylesheets: Vec<String>,
} }
@ -284,7 +287,19 @@ impl Document {
path: None, path: None,
placeholders: Vec::new(), placeholders: Vec::new(),
config: Configuration::default(), config: Configuration::default(),
bibliography: Bibliography::new(), bibliography: BibManager::new(),
stylesheets: Vec::new(),
}
}
pub fn new_with_manager(is_root: bool, bibliography: BibManager) -> Self {
Self {
elements: Vec::new(),
is_root,
path: None,
placeholders: Vec::new(),
config: Configuration::default(),
bibliography,
stylesheets: Vec::new(), stylesheets: Vec::new(),
} }
} }
@ -352,7 +367,6 @@ impl Document {
if let Some(doc) = &mut anchor.document { if let Some(doc) = &mut anchor.document {
self.placeholders.append(&mut doc.placeholders); self.placeholders.append(&mut doc.placeholders);
self.bibliography.combine(&mut doc.bibliography);
doc.elements.reverse(); doc.elements.reverse();
self.elements.append(&mut doc.elements); self.elements.append(&mut doc.elements);
anchor.document = None; anchor.document = None;
@ -381,7 +395,7 @@ impl Document {
self.postprocess_imports(); self.postprocess_imports();
if self.is_root { if self.is_root {
self.process_definitions(); self.process_definitions();
self.bibliography.assign_entry_data(); self.bibliography.assign_entries_to_references();
self.process_placeholders(); self.process_placeholders();
} }
} }
@ -604,6 +618,7 @@ impl Placeholder {
pub trait Metadata { pub trait Metadata {
fn get_bool(&self, key: &str) -> bool; fn get_bool(&self, key: &str) -> bool;
fn get_string(&self, key: &str) -> Option<String>; fn get_string(&self, key: &str) -> Option<String>;
fn get_string_map(&self) -> HashMap<String, String>;
} }
impl Metadata for InlineMetadata { impl Metadata for InlineMetadata {
@ -622,6 +637,21 @@ impl Metadata for InlineMetadata {
None None
} }
} }
fn get_string_map(&self) -> HashMap<String, String> {
let mut string_map = HashMap::new();
for (k, v) in &self.data {
match v {
MetadataValue::String(s) => string_map.insert(k.clone(), s.clone()),
MetadataValue::Bool(b) => string_map.insert(k.clone(), b.to_string()),
MetadataValue::Float(f) => string_map.insert(k.clone(), f.to_string()),
MetadataValue::Integer(i) => string_map.insert(k.clone(), i.to_string()),
_ => None,
};
}
string_map
}
} }
impl Image { impl Image {
@ -650,3 +680,47 @@ impl Image {
} }
} }
} }
#[derive(Clone, Debug)]
pub struct BibEntry {
pub key: String,
pub entry: BibliographyEntryReference,
}
#[derive(Clone, Debug)]
pub struct BibReference {
pub(crate) key: String,
pub(crate) entry_anchor: Arc<Mutex<BibRefAnchor>>,
pub(crate) display: Option<ConfigRefEntry>,
}
impl BibReference {
pub fn new(
key: String,
display: Option<ConfigRefEntry>,
anchor: Arc<Mutex<BibRefAnchor>>,
) -> Self {
Self {
key: key.to_string(),
display,
entry_anchor: anchor,
}
}
pub(crate) fn get_formatted(&self) -> String {
if let Some(entry) = &self.entry_anchor.lock().unwrap().entry {
let entry = entry.lock().unwrap();
if let Some(display) = &self.display {
let display = display.read().unwrap();
let mut template = PlaceholderTemplate::new(display.get().as_string());
let mut value_map = HashMap::new();
value_map.insert("key".to_string(), entry.key());
template.set_replacements(value_map);
return template.render();
}
return format!("{}", entry.key());
}
return "citation needed".to_string();
}
}

@ -1,7 +1,5 @@
use crate::elements::*; use crate::elements::*;
use crate::format::PlaceholderTemplate; use crate::format::PlaceholderTemplate;
use crate::references::bibliography::{BibEntry, BibReference};
use crate::references::configuration::Value;
use crate::references::templates::{Template, TemplateVariable}; use crate::references::templates::{Template, TemplateVariable};
use asciimath_rs::format::mathml::ToMathML; use asciimath_rs::format::mathml::ToMathML;
use htmlescape::{encode_attribute, encode_minimal}; use htmlescape::{encode_attribute, encode_minimal};
@ -43,7 +41,7 @@ impl ToHtml for Line {
Line::Ruler(ruler) => ruler.to_html(), Line::Ruler(ruler) => ruler.to_html(),
Line::Anchor(anchor) => anchor.to_html(), Line::Anchor(anchor) => anchor.to_html(),
Line::Centered(centered) => centered.to_html(), Line::Centered(centered) => centered.to_html(),
Line::BibEntry(bib) => bib.read().unwrap().to_html(), Line::BibEntry(_) => "".to_string(),
} }
} }
} }
@ -569,55 +567,6 @@ impl ToHtml for BibReference {
} }
} }
impl ToHtml for BibEntry {
fn to_html(&self) -> String {
if !self.is_visible() {
return "".to_string();
}
if let Some(display) = &self.display {
let display = display.read().unwrap();
if let Value::Template(template) = display.get() {
let replacements = self
.as_map()
.iter()
.map(|(k, v)| {
(
k.clone(),
Element::Inline(Box::new(Inline::Plain(PlainText {
value: v.clone(),
}))),
)
})
.collect();
return template
.render(replacements)
.iter()
.fold("".to_string(), |a, b| format!("{}{}", a, b.to_html()));
}
let mut template = PlaceholderTemplate::new(display.get().as_string());
template.set_replacements(self.as_map());
format!(
"<span id='{}'>{}</span>",
encode_attribute(self.key.as_str()),
encode_minimal(template.render().as_str())
)
} else {
if let Some(url) = &self.url {
format!(
"<a id={1} href='{0}'>{1}</a>",
encode_attribute(url.as_str()),
encode_minimal(self.key.as_str())
)
} else {
format!(
"<span id='{0}'><u>{0}</u></span>",
encode_attribute(self.key.as_str())
)
}
}
}
}
impl ToHtml for Template { impl ToHtml for Template {
fn to_html(&self) -> String { fn to_html(&self) -> String {
self.text self.text

@ -1,11 +1,12 @@
use super::{ParseError, ParseResult}; use super::{ParseError, ParseResult};
use crate::elements::tokens::*; use crate::elements::tokens::*;
use crate::elements::BibReference;
use crate::elements::*; use crate::elements::*;
use crate::parser::block::ParseBlock; use crate::parser::block::ParseBlock;
use crate::references::bibliography::BibReference;
use crate::references::configuration::keys::BIB_REF_DISPLAY; use crate::references::configuration::keys::BIB_REF_DISPLAY;
use crate::references::templates::{GetTemplateVariables, Template, TemplateVariable}; use crate::references::templates::{GetTemplateVariables, Template, TemplateVariable};
use crate::Parser; use crate::Parser;
use bibliographix::references::bib_reference::BibRef;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@ -301,13 +302,18 @@ impl ParseInline for Parser {
self.ctm self.ctm
.get_string_until_any_or_rewind(&[BIBREF_CLOSE], &[SPACE, LB], start_index)?; .get_string_until_any_or_rewind(&[BIBREF_CLOSE], &[SPACE, LB], start_index)?;
self.ctm.seek_one()?; self.ctm.seek_one()?;
let bib_ref = BibRef::new(key.clone());
let ref_entry = Arc::new(RwLock::new(BibReference::new( let ref_entry = Arc::new(RwLock::new(BibReference::new(
key, key,
self.document.config.get_ref_entry(BIB_REF_DISPLAY), self.document.config.get_ref_entry(BIB_REF_DISPLAY),
bib_ref.anchor(),
))); )));
self.document self.document
.bibliography .bibliography
.add_ref_entry(Arc::clone(&ref_entry)); .root_ref_anchor()
.lock()
.unwrap()
.insert(bib_ref);
Ok(ref_entry) Ok(ref_entry)
} }

@ -1,10 +1,13 @@
use super::ParseResult; use super::ParseResult;
use crate::elements::tokens::*; use crate::elements::tokens::*;
use crate::elements::{BibEntry, Metadata};
use crate::elements::{Cell, Centered, Header, Inline, Line, ListItem, Row, Ruler, TextLine}; use crate::elements::{Cell, Centered, Header, Inline, Line, ListItem, Row, Ruler, TextLine};
use crate::parser::inline::ParseInline; use crate::parser::inline::ParseInline;
use crate::references::bibliography::BibEntry;
use crate::Parser; use crate::Parser;
use std::sync::{Arc, RwLock}; use bibliographix::bibliography::bibliography_entry::BibliographyEntry;
use bibliographix::bibliography::keys::{K_KEY, K_TYPE, K_URL, T_WEBSITE};
use bibliographix::bibliography::FromHashMap;
use std::collections::HashMap;
pub(crate) trait ParseLine { pub(crate) trait ParseLine {
fn parse_line(&mut self) -> ParseResult<Line>; fn parse_line(&mut self) -> ParseResult<Line>;
@ -14,7 +17,7 @@ pub(crate) trait ParseLine {
fn parse_centered(&mut self) -> ParseResult<Centered>; fn parse_centered(&mut self) -> ParseResult<Centered>;
fn parse_ruler(&mut self) -> ParseResult<Ruler>; fn parse_ruler(&mut self) -> ParseResult<Ruler>;
fn parse_text_line(&mut self) -> ParseResult<TextLine>; fn parse_text_line(&mut self) -> ParseResult<TextLine>;
fn parse_bib_entry(&mut self) -> ParseResult<Arc<RwLock<BibEntry>>>; fn parse_bib_entry(&mut self) -> ParseResult<BibEntry>;
} }
impl ParseLine for Parser { impl ParseLine for Parser {
@ -174,7 +177,7 @@ impl ParseLine for Parser {
} }
} }
fn parse_bib_entry(&mut self) -> ParseResult<Arc<RwLock<BibEntry>>> { fn parse_bib_entry(&mut self) -> ParseResult<BibEntry> {
let start_index = self.ctm.get_index(); let start_index = self.ctm.get_index();
self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.seek_any(&INLINE_WHITESPACE)?;
self.ctm.assert_char(&BIB_KEY_OPEN, Some(start_index))?; self.ctm.assert_char(&BIB_KEY_OPEN, Some(start_index))?;
@ -188,18 +191,49 @@ impl ParseLine for Parser {
self.ctm.seek_any(&INLINE_WHITESPACE)?; self.ctm.seek_any(&INLINE_WHITESPACE)?;
let entry = if let Ok(meta) = self.parse_inline_metadata() { let entry = if let Ok(meta) = self.parse_inline_metadata() {
BibEntry::from_metadata(key, Box::new(meta), &self.document.config) let mut string_map = meta.get_string_map();
string_map.insert(K_KEY.to_string(), key.clone());
if let Some(entry) = BibliographyEntry::from_hash_map(&string_map) {
*entry
} else {
eprintln!("Failed to parse bib entry with key {}", key);
return Err(self.ctm.rewind_with_error(start_index));
}
} else { } else {
let url = self let url = self
.ctm .ctm
.get_string_until_any_or_rewind(&[LB], &[], start_index)?; .get_string_until_any_or_rewind(&[LB], &[], start_index)?;
BibEntry::from_url(key, url, &self.document.config) let mut map = HashMap::new();
map.insert(K_TYPE.to_string(), T_WEBSITE.to_string());
map.insert(K_URL.to_string(), url);
map.insert(K_KEY.to_string(), key.clone());
if let Some(entry) = BibliographyEntry::from_hash_map(&map) {
*entry
} else {
eprintln!("Failed to parse bib entry with key {}", key);
return Err(self.ctm.rewind_with_error(start_index));
}
}; };
let entry_ref = Arc::new(RwLock::new(entry));
self.document self.document
.bibliography .bibliography
.add_bib_entry(Arc::clone(&entry_ref)); .entry_dictionary()
.lock()
Ok(entry_ref) .unwrap()
.insert(entry);
Ok(BibEntry {
entry: self
.document
.bibliography
.entry_dictionary()
.lock()
.unwrap()
.get(&key)
.unwrap(),
key,
})
} }
} }

@ -5,6 +5,7 @@ pub(crate) mod line;
use self::block::ParseBlock; use self::block::ParseBlock;
use crate::elements::{Document, ImportAnchor}; use crate::elements::{Document, ImportAnchor};
use crate::references::configuration::Configuration; use crate::references::configuration::Configuration;
use bibliographix::bib_manager::BibManager;
use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult}; use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult};
use colored::*; use colored::*;
use crossbeam_utils::sync::WaitGroup; use crossbeam_utils::sync::WaitGroup;
@ -42,6 +43,7 @@ impl Parser {
Arc::new(Mutex::new(Vec::new())), Arc::new(Mutex::new(Vec::new())),
false, false,
Box::new(BufReader::new(f)), Box::new(BufReader::new(f)),
BibManager::new(),
)) ))
} }
@ -58,17 +60,24 @@ impl Parser {
Arc::new(Mutex::new(Vec::new())), Arc::new(Mutex::new(Vec::new())),
false, false,
Box::new(Cursor::new(text_bytes.to_vec())), Box::new(Cursor::new(text_bytes.to_vec())),
BibManager::new(),
) )
} }
/// Creates a child parser from string text /// Creates a child parser from string text
pub fn child(text: String, path: PathBuf, paths: Arc<Mutex<Vec<PathBuf>>>) -> Self { pub fn child(
text: String,
path: PathBuf,
paths: Arc<Mutex<Vec<PathBuf>>>,
bib_manager: BibManager,
) -> Self {
let text_bytes = text.as_bytes(); let text_bytes = text.as_bytes();
Self::create( Self::create(
Some(PathBuf::from(path)), Some(PathBuf::from(path)),
paths, paths,
true, true,
Box::new(Cursor::new(text_bytes.to_vec())), Box::new(Cursor::new(text_bytes.to_vec())),
bib_manager,
) )
} }
@ -76,6 +85,7 @@ impl Parser {
pub fn child_from_file( pub fn child_from_file(
path: PathBuf, path: PathBuf,
paths: Arc<Mutex<Vec<PathBuf>>>, paths: Arc<Mutex<Vec<PathBuf>>>,
bib_manager: BibManager,
) -> Result<Self, io::Error> { ) -> Result<Self, io::Error> {
let f = File::open(&path)?; let f = File::open(&path)?;
Ok(Self::create( Ok(Self::create(
@ -83,6 +93,7 @@ impl Parser {
paths, paths,
true, true,
Box::new(BufReader::new(f)), Box::new(BufReader::new(f)),
bib_manager,
)) ))
} }
@ -91,6 +102,7 @@ impl Parser {
paths: Arc<Mutex<Vec<PathBuf>>>, paths: Arc<Mutex<Vec<PathBuf>>>,
is_child: bool, is_child: bool,
mut reader: Box<dyn BufRead>, mut reader: Box<dyn BufRead>,
bib_manager: BibManager,
) -> Self { ) -> Self {
if let Some(path) = path.clone() { if let Some(path) = path.clone() {
paths.lock().unwrap().push(path.clone()) paths.lock().unwrap().push(path.clone())
@ -103,7 +115,7 @@ impl Parser {
text.push('\n'); text.push('\n');
} }
let document = Document::new(!is_child); let document = Document::new_with_manager(!is_child, bib_manager);
Self { Self {
sections: Vec::new(), sections: Vec::new(),
section_nesting: 0, section_nesting: 0,
@ -178,9 +190,10 @@ impl Parser {
let wg = self.wg.clone(); let wg = self.wg.clone();
let paths = Arc::clone(&self.paths); let paths = Arc::clone(&self.paths);
let config = self.document.config.clone(); let config = self.document.config.clone();
let bibliography = self.document.bibliography.create_child();
let _ = thread::spawn(move || { let _ = thread::spawn(move || {
let mut parser = Parser::child_from_file(path, paths).unwrap(); let mut parser = Parser::child_from_file(path, paths, bibliography).unwrap();
parser.set_config(config); parser.set_config(config);
let document = parser.parse(); let document = parser.parse();
anchor_clone.write().unwrap().set_document(document); anchor_clone.write().unwrap().set_document(document);

@ -1,200 +1 @@
use crate::elements::Metadata;
use crate::format::PlaceholderTemplate;
use crate::references::configuration::keys::{BIB_DISPLAY, BIB_HIDE_UNUSED};
use crate::references::configuration::{ConfigRefEntry, Configuration, Value};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
const B_NUMBER: &str = "number";
const B_AUTHOR: &str = "author";
const B_DATE: &str = "date";
const B_URL: &str = "url";
const B_TITLE: &str = "title";
const B_PUBLISHER: &str = "publisher";
const B_NOTES: &str = "notes";
#[derive(Clone, Debug)]
pub struct BibEntry {
pub(crate) number: usize,
pub(crate) ref_count: usize,
pub key: String,
pub author: Option<String>,
pub date: Option<String>,
pub url: Option<String>,
pub title: Option<String>,
pub publisher: Option<String>,
pub notes: Option<String>,
pub display: Option<ConfigRefEntry>,
pub hide_unused: Option<ConfigRefEntry>,
}
#[derive(Clone, Debug)]
pub struct BibReference {
pub(crate) key: String,
pub(crate) reference_entry: Option<Arc<RwLock<BibEntry>>>,
pub(crate) display: Option<ConfigRefEntry>,
}
#[derive(Clone, Debug)]
pub struct Bibliography {
entries: HashMap<String, Arc<RwLock<BibEntry>>>,
references: Vec<Arc<RwLock<BibReference>>>,
}
impl BibEntry {
pub fn as_map(&self) -> HashMap<String, String> {
let mut map = HashMap::new();
map.insert(B_NUMBER.to_string(), format!("{}", self.number));
map.insert("key".to_string(), self.key.clone());
if let Some(author) = &self.author {
map.insert(B_AUTHOR.to_string(), author.clone());
}
if let Some(date) = &self.date {
map.insert(B_DATE.to_string(), date.clone());
}
if let Some(url) = &self.url {
map.insert(B_URL.to_string(), url.clone());
}
if let Some(title) = &self.title {
map.insert(B_TITLE.to_string(), title.clone());
}
if let Some(publisher) = &self.publisher {
map.insert(B_PUBLISHER.to_string(), publisher.clone());
}
if let Some(notes) = &self.notes {
map.insert(B_NOTES.to_string(), notes.clone());
}
map
}
pub fn from_metadata(key: String, data: Box<dyn Metadata>, config: &Configuration) -> Self {
BibEntry {
number: 0,
ref_count: 0,
key,
author: data.get_string(B_AUTHOR),
date: data.get_string(B_DATE),
url: data.get_string(B_URL),
title: data.get_string(B_TITLE),
publisher: data.get_string(B_PUBLISHER),
notes: data.get_string(B_NOTES),
display: config.get_ref_entry(BIB_DISPLAY),
hide_unused: config.get_ref_entry(BIB_HIDE_UNUSED),
}
}
pub fn from_url(key: String, url: String, config: &Configuration) -> Self {
BibEntry {
number: 0,
ref_count: 0,
key,
author: None,
date: None,
url: Some(url),
title: None,
publisher: None,
notes: None,
display: config.get_ref_entry(BIB_DISPLAY),
hide_unused: config.get_ref_entry(BIB_HIDE_UNUSED),
}
}
pub fn set_number(&mut self, number: usize) {
self.number = number
}
pub fn set_ref_count(&mut self, number: usize) {
self.ref_count = number
}
pub fn is_visible(&self) -> bool {
if let Some(hide_cfg) = &self.hide_unused {
let hide_cfg = hide_cfg.read().unwrap();
if let Value::Bool(b) = hide_cfg.get() {
if *b && self.ref_count == 0 {
return false;
}
}
}
true
}
}
impl BibReference {
pub fn new(key: String, display: Option<ConfigRefEntry>) -> Self {
Self {
key: key.to_string(),
display,
reference_entry: None,
}
}
/// sets the reference to the bib entry
pub(crate) fn set_entry(&mut self, entry: Arc<RwLock<BibEntry>>) {
self.reference_entry = Some(entry)
}
pub(crate) fn get_formatted(&self) -> String {
if let Some(entry) = &self.reference_entry {
let entry = entry.read().unwrap();
if let Some(display) = &self.display {
let display = display.read().unwrap();
let mut template = PlaceholderTemplate::new(display.get().as_string());
template.set_replacements(entry.as_map());
return template.render();
}
return format!("{}", entry.number);
}
return "citation needed".to_string();
}
}
impl Bibliography {
pub fn new() -> Self {
Self {
entries: HashMap::new(),
references: Vec::new(),
}
}
pub(crate) fn assign_entry_data(&mut self) {
let mut count = 0;
self.references.iter().for_each(|e| {
let mut reference = e.write().unwrap();
if let Some(entry) = self.entries.get(&reference.key) {
{
let mut entry_raw = entry.write().unwrap();
let ref_count = entry_raw.ref_count;
entry_raw.set_ref_count(ref_count + 1);
}
reference.set_entry(Arc::clone(entry));
}
});
self.entries.iter().for_each(|(_, e)| {
let mut entry = e.write().unwrap();
if entry.is_visible() {
count += 1;
entry.set_number(count)
}
});
}
pub fn add_ref_entry(&mut self, entry: Arc<RwLock<BibReference>>) {
self.references.push(entry)
}
pub fn add_bib_entry(&mut self, entry: Arc<RwLock<BibEntry>>) {
let key = entry.read().unwrap().key.clone();
self.entries.insert(key, entry);
}
pub fn combine(&mut self, other: &mut Bibliography) {
let other_entries = other.entries.clone();
other.entries = HashMap::new();
self.entries.extend(other_entries.into_iter());
self.references.append(&mut other.references);
}
}

@ -1,4 +1,4 @@
[bibliography] [bibliography]
entry_display = "{{number}}: {{author}} - {{title}} - {{date}} - {{url}}" entry_display = "{{number}}: {{author}} - {{title}} - {{date}} - {{url}}"
reference_display = "{{number}}" reference_display = "{{key}}"
hide_unused = true hide_unused = true
Loading…
Cancel
Save