Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 12 additions & 14 deletions src/inserters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn append_to_file(path: &str, content: &str) -> std::io::Result<()> {
Ok(())
}

fn generate_mdx_bibliography(entries: &Vec<MatchedCitationDisambiguated>) -> String {
fn generate_mdx_bibliography(entries: &[MatchedCitationDisambiguated]) -> String {
let mut bib_html = String::new();

if entries.is_empty() {
Expand All @@ -181,7 +181,7 @@ fn generate_mdx_bibliography(entries: &Vec<MatchedCitationDisambiguated>) -> Str
for entry in prepared_entries {
bib_html.push_str("- ");
bib_html.push_str(&entry);
bib_html.push_str("\n");
bib_html.push('\n');
}

bib_html.push_str("</div>\n");
Expand All @@ -198,34 +198,32 @@ fn generate_mdx_authors(metadata: &Metadata) -> String {

if let Some(authors) = &metadata.authors {
mdx_html.push_str("\n**Authors** \n");
mdx_html.push_str(&authors);
mdx_html.push_str("\n");
mdx_html.push_str(authors);
mdx_html.push('\n');
}
if let Some(editors) = &metadata.editors {
mdx_html.push_str("\n**Editors** \n");
mdx_html.push_str(&editors);
mdx_html.push_str("\n");
mdx_html.push_str(editors);
mdx_html.push('\n');
}
if let Some(contributors) = &metadata.contributors {
mdx_html.push_str("\n**Contributors** \n");
mdx_html.push_str(&contributors);
mdx_html.push_str("\n");
mdx_html.push_str(contributors);
mdx_html.push('\n');
}

mdx_html
}

fn generate_notes_heading(markdown: &String) -> String {
fn generate_notes_heading(markdown: &str) -> String {
let mut mdx_notes_heading = String::new();

let footnote_regex = Regex::new(r"\[\^1\]").unwrap();

'outer: for line in markdown.lines() {
for _captures in footnote_regex.captures_iter(line) {
mdx_notes_heading.push_str("\n**Notes**");
break 'outer;
}
if markdown.lines().any(|line| footnote_regex.is_match(line)) {
mdx_notes_heading.push_str("\n**Notes**");
}

mdx_notes_heading
}

Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl Prepyrus {
/// Retrieve all bibliography entries from the bibliography file.
/// Returns a vector of `biblatex::Entry`.
pub fn get_all_bib_entries(bib_file: &str) -> Result<Vec<biblatex::Entry>, BibliographyError> {
Ok(BiblatexUtils::retrieve_bibliography_entries(bib_file)?)
BiblatexUtils::retrieve_bibliography_entries(bib_file)
}

/// Retrieve all MDX file paths from the target directory.
Expand All @@ -196,7 +196,7 @@ impl Prepyrus {
mdx_paths: Vec<String>,
all_entries: &Vec<Entry>,
) -> Result<Vec<ArticleFileData>, Error> {
validators::verify_mdx_files(mdx_paths, &all_entries)
validators::verify_mdx_files(mdx_paths, all_entries)
}

/// Process the MDX files by injecting bibliography and other details into the MDX files.
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use prepyrus::{cli::Mode, Prepyrus};

fn main() {
let _ = run().unwrap_or_else(|e| {
run().unwrap_or_else(|e| {
eprintln!("Error: {}", e);
std::process::exit(1);
});
Expand Down
114 changes: 59 additions & 55 deletions src/transformers.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use biblatex::Person;
use biblatex::{Entry, EntryType};
use std::cmp::Ordering;
use std::collections::HashMap;
use utils::BiblatexUtils;
use validators::{MatchedCitation, MatchedCitationDisambiguated};
Expand All @@ -9,7 +10,7 @@ use crate::validators;
use crate::validators::ArticleFileData;

/// Transform a list of entries into a list of strings according to the Chicago bibliography style.
pub fn entries_to_strings(entries: &Vec<MatchedCitationDisambiguated>) -> Vec<String> {
pub fn entries_to_strings(entries: &[MatchedCitationDisambiguated]) -> Vec<String> {
let sorted_entries = sort_entries(entries);
let mut strings_output: Vec<String> = Vec::new();

Expand Down Expand Up @@ -64,7 +65,7 @@ pub fn disambiguate_matched_citations(
let author_year_key = format!("{}-{}", author_last_name, year);
author_year_groups
.entry(author_year_key)
.or_insert_with(Vec::new)
.or_default()
.push(citation);
}

Expand Down Expand Up @@ -126,7 +127,7 @@ fn transform_book_entry(matched_citation: &MatchedCitationDisambiguated) -> Stri
let title = extract_title(&matched_citation.entry);
let publisher = extract_publisher(&matched_citation.entry);
let address = extract_address(&matched_citation.entry);
let translators = matched_citation.entry.translator().unwrap_or(Vec::new());
let translators = matched_citation.entry.translator().unwrap_or_default();
let doi = matched_citation.entry.doi().unwrap_or("".to_string());

add_authors(author, &mut book_string);
Expand All @@ -150,7 +151,7 @@ fn transform_article_entry(matched_citation: &MatchedCitationDisambiguated) -> S
let volume = extract_volume(&matched_citation.entry);
let number = extract_number(&matched_citation.entry);
let pages = extract_pages(&matched_citation.entry);
let translators = matched_citation.entry.translator().unwrap_or(Vec::new());
let translators = matched_citation.entry.translator().unwrap_or_default();
let doi = matched_citation.entry.doi().unwrap_or("".to_string());

add_authors(author, &mut article_string);
Expand All @@ -171,20 +172,25 @@ fn generate_contributors(
contributor_description: String,
) -> String {
let mut contributors_str = String::new();
if contributors.len() > 1 {
contributors_str.push_str(&format!("{} by ", contributor_description));
for (i, person) in contributors.iter().enumerate() {
if i == contributors.len() - 1 {
contributors_str.push_str(&format!("and {} {}. ", person.given_name, person.name));
} else {
contributors_str.push_str(&format!("{} {}, ", person.given_name, person.name));
match contributors.len().cmp(&1) {
Ordering::Greater => {
contributors_str.push_str(&format!("{} by ", contributor_description));
for (i, person) in contributors.iter().enumerate() {
if i == contributors.len() - 1 {
contributors_str
.push_str(&format!("and {} {}. ", person.given_name, person.name));
} else {
contributors_str.push_str(&format!("{} {}, ", person.given_name, person.name));
}
}
}
} else if contributors.len() == 1 {
contributors_str.push_str(&format!(
"{} by {} {}. ",
contributor_description, contributors[0].given_name, contributors[0].name
));
Ordering::Equal => {
contributors_str.push_str(&format!(
"{} by {} {}. ",
contributor_description, contributors[0].given_name, contributors[0].name
));
}
Ordering::Less => {}
}
contributors_str
}
Expand All @@ -200,30 +206,36 @@ fn add_authors(author: Vec<biblatex::Person>, bib_html: &mut String) {

/// Returns Chicago style format for authors. Handles the case when there are multiple authors.
fn format_authors(author: Vec<biblatex::Person>) -> String {
if author.len() > 2 {
return format!("{}, {} et al. ", author[0].name, author[0].given_name);
} else if author.len() == 2 {
// In Chicago style, when listing multiple authors in a bibliography entry,
// only the first author's name is inverted (i.e., "Last, First"). The second and subsequent
// authors' names are written in standard order (i.e., "First Last").
// This rule helps differentiate the primary author from co-authors.
return format!(
"{}, {} and {} {}. ",
author[0].name, author[0].given_name, author[1].given_name, author[1].name
);
} else {
return format!("{}, {}. ", author[0].name, author[0].given_name);
match author.len().cmp(&2) {
Ordering::Greater => {
format!("{}, {} et al. ", author[0].name, author[0].given_name)
}
Ordering::Equal => {
// In Chicago style, when listing multiple authors in a bibliography entry,
// only the first author's name is inverted (i.e., "Last, First"). The second and subsequent
// authors' names are written in standard order (i.e., "First Last").
// This rule helps differentiate the primary author from co-authors.
format!(
"{}, {} and {} {}. ",
author[0].name, author[0].given_name, author[1].given_name, author[1].name
)
}
Ordering::Less => {
format!("{}, {}. ", author[0].name, author[0].given_name)
}
}
}

/// Returns Chicago style format for authors. Handles the case when there are multiple authors.
fn format_authors_last_name_only(author: Vec<biblatex::Person>) -> String {
if author.len() > 2 {
return format!("{} et al.", author[0].name);
} else if author.len() == 2 {
return format!("{} and {}", author[0].name, author[1].name);
} else {
return format!("{}", author[0].name);
match author.len().cmp(&2) {
Ordering::Greater => {
format!("{} et al.", author[0].name)
}
Ordering::Equal => {
format!("{} and {}", author[0].name, author[1].name)
}
Ordering::Less => author[0].name.to_string(),
}
}

Expand Down Expand Up @@ -272,8 +284,8 @@ fn add_journal_volume_number_pages(
}

/// Sort entries by author's last name.
fn sort_entries(entries: &Vec<MatchedCitationDisambiguated>) -> Vec<MatchedCitationDisambiguated> {
let mut sorted_entries = entries.clone();
fn sort_entries(entries: &[MatchedCitationDisambiguated]) -> Vec<MatchedCitationDisambiguated> {
let mut sorted_entries = entries.to_vec();

sorted_entries.sort_by(|a, b| {
let a_authors = a.entry.author().unwrap_or_default();
Expand All @@ -292,7 +304,7 @@ fn sort_entries(entries: &Vec<MatchedCitationDisambiguated>) -> Vec<MatchedCitat
// Compare by year
let a_year = &a.year_disambiguated;
let b_year = &b.year_disambiguated;
let cmp_year = a_year.cmp(&b_year);
let cmp_year = a_year.cmp(b_year);
if cmp_year != std::cmp::Ordering::Equal {
return cmp_year;
}
Expand All @@ -307,7 +319,7 @@ fn sort_entries(entries: &Vec<MatchedCitationDisambiguated>) -> Vec<MatchedCitat
}

/// Helper to generate a sortable author string
fn author_key(authors: &Vec<Person>) -> String {
fn author_key(authors: &[Person]) -> String {
authors
.first()
.map(|p| p.name.clone().to_lowercase())
Expand All @@ -317,57 +329,49 @@ fn author_key(authors: &Vec<Person>) -> String {
/// Title of the entry.
fn extract_title(entry: &Entry) -> String {
let title_spanned = entry.title().unwrap();
let title = BiblatexUtils::extract_spanned_chunk(title_spanned);
title
BiblatexUtils::extract_spanned_chunk(title_spanned)
}

/// Publisher of the entry.
fn extract_publisher(entry: &Entry) -> String {
let publisher_spanned = entry.publisher().unwrap();
let publisher = BiblatexUtils::extract_publisher(&publisher_spanned);
publisher
BiblatexUtils::extract_publisher(&publisher_spanned)
}

/// Address of the publisher.
fn extract_address(entry: &Entry) -> String {
let address_spanned = entry.address().unwrap();
let address = BiblatexUtils::extract_spanned_chunk(address_spanned);
address
BiblatexUtils::extract_spanned_chunk(address_spanned)
}

/// Year of entry.
fn extract_date(entry: &Entry) -> i32 {
let date = entry.date().unwrap();
let year = BiblatexUtils::extract_year_from_date(&date, entry.key.clone()).unwrap();
year
BiblatexUtils::extract_year_from_date(&date, entry.key.clone()).unwrap()
}

/// Name of the journal of the article.
fn extract_journal(entry: &Entry) -> String {
let journal_spanned = entry.journal().unwrap();
let journal = BiblatexUtils::extract_spanned_chunk(&journal_spanned);
journal
BiblatexUtils::extract_spanned_chunk(journal_spanned)
}

/// Volume of the journal.
fn extract_volume(entry: &Entry) -> i64 {
let volume_permissive = entry.volume().unwrap();
let volume = BiblatexUtils::extract_volume(&volume_permissive);
volume
BiblatexUtils::extract_volume(&volume_permissive)
}

/// Number of the journal.
fn extract_number(entry: &Entry) -> String {
let number_spanned = entry.number().unwrap();
let number = BiblatexUtils::extract_spanned_chunk(&number_spanned);
number
BiblatexUtils::extract_spanned_chunk(number_spanned)
}

/// Pages of the article.
fn extract_pages(entry: &Entry) -> String {
let pages_permissive = entry.pages().unwrap();
let pages = BiblatexUtils::extract_pages(&pages_permissive);
pages
BiblatexUtils::extract_pages(&pages_permissive)
}

/// Create disambiguated citation with letter (e.g., "@hegel2020logic, 123" -> "Hegel 2020a")
Expand Down
6 changes: 3 additions & 3 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl BiblatexUtils {
DateValue::Before(datetime) => Ok(datetime.year),
DateValue::Between(start, _end) => Ok(start.year), // Or use end.year
},
_ => return Err(format!("Unable to retrieve year for: {}", reference)),
_ => Err(format!("Unable to retrieve year for: {}", reference)),
}
}

Expand Down Expand Up @@ -103,7 +103,7 @@ impl BiblatexUtils {
}

/// Extract the publisher from a `Spanned<Chunk>` vector.
pub fn extract_publisher(publisher_data: &Vec<Vec<Spanned<Chunk>>>) -> String {
pub fn extract_publisher(publisher_data: &[Vec<Spanned<Chunk>>]) -> String {
publisher_data
.iter()
.flat_map(|inner_vec| {
Expand Down Expand Up @@ -171,7 +171,7 @@ impl Utils {
/// Extract paths of MDX files from a directory and its subdirectories.
/// Optionally, provide a list of paths to ignore.
pub fn extract_paths(path: &str, ignore_paths: Option<Vec<String>>) -> io::Result<Vec<String>> {
let exceptions = ignore_paths.unwrap_or_else(|| Vec::new());
let exceptions = ignore_paths.unwrap_or_default();
let mdx_paths_raw = Self::extract_mdx_paths(path).unwrap();
let mdx_paths = Self::filter_mdx_paths_for_exceptions(mdx_paths_raw, exceptions);

Expand Down
Loading