Direct Translation from Biblatex to CSL - #497
Conversation
|
I conducted a test against the example entries in the standard GB/T 7714—2025 with https://github.com/citation-style-language/styles/blob/995f064bd45846c000080286186d81d0b97c96cc/china-national-standard-gb-t-7714-2025-numeric.csl and https://github.com/typst-doc-cn/bib-csl-dev-data/blob/42e5c083a0fbc07aa96c15a5a5746b2804c88a9c/data/GB-T_7714—2025.better.bib. The meaning of the metrics, taking the last as an example:
Test codeThe results of v0.10.1 are generated from https://github.com/YDX-2147483647/gb7714-bench/blob/b4ab37c50a2cc9ca9e0a89e10ded6feac1339eda/processors/typst.nu. The results of this PR are generated by the following codes. diff --git a/crates/hayagriva-biblatex/Cargo.toml b/crates/hayagriva-biblatex/Cargo.toml
index 40eaee2..976e84c 100644
--- a/crates/hayagriva-biblatex/Cargo.toml
+++ b/crates/hayagriva-biblatex/Cargo.toml
@@ -11,6 +11,7 @@ keywords.workspace = true
[dependencies]
hayagriva-core = { path = "../hayagriva-core", features = ["biblatex"] }
-biblatex = { workspace = true, features = ["unic-langid"] }
+biblatex = { workspace = true, features = ["unic-langid", "serde"] }
citationberg = { workspace = true }
unic-langid = { workspace = true }
+serde_json = "1"
diff --git a/crates/hayagriva-biblatex/src/lib.rs b/crates/hayagriva-biblatex/src/lib.rs
index 958a915..870fd56 100644
--- a/crates/hayagriva-biblatex/src/lib.rs
+++ b/crates/hayagriva-biblatex/src/lib.rs
@@ -14,8 +14,19 @@ use hayagriva_core::{
};
use unic_langid::LanguageIdentifier;
+pub use biblatex;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Entry(pub biblatex::Entry);
+// `biblatex::Entry` doesn't derive `Hash`.
+impl std::hash::Hash for Entry {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ let bytes = serde_json::to_vec(&self.0).unwrap();
+ bytes.hash(state);
+ }
+}
+
impl EntryLike for Entry {
fn resolve_number_variable(
&self,# crates/foo/Cargo.toml
[package]
name = "foo"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
keywords.workspace = true
[dependencies]
hayagriva-archive = { path = "../hayagriva-archive" }
hayagriva-biblatex = { path = "../hayagriva-biblatex" }
hayagriva-csl = { path = "../hayagriva-csl" }
hayagriva-format = { path = "../hayagriva-format" }// crates/foo/src/main.rs
use hayagriva_archive::locales;
use hayagriva_biblatex::{Entry, biblatex::Bibliography};
use hayagriva_csl::{
BibliographyDriver, BibliographyRequest, CitationItem, CitationRequest,
};
use hayagriva_format::citationberg::IndependentStyle;
mod strings;
use strings::{GB_7714_2025_NUMERIC_COMPLIANT_CSL, GB_T_7714_2025_BETTER_BIB};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let locales = locales();
let style = IndependentStyle::from_xml(GB_7714_2025_NUMERIC_COMPLIANT_CSL)?;
let entries: Vec<Entry> = Bibliography::parse(GB_T_7714_2025_BETTER_BIB)?
.into_iter()
.map(|entry| Entry(entry))
.collect();
let mut driver: BibliographyDriver<'_, Entry> = BibliographyDriver::new();
driver.citation(CitationRequest::new(
entries.iter().map(CitationItem::with_entry).collect(),
&style,
None,
&locales,
Some(1),
));
let result = driver.finish(BibliographyRequest {
style: &style,
locale: None,
locale_files: &locales,
});
let mut output = String::new();
for row in result.bibliography.map(|b| b.items).unwrap_or_default() {
if let Some(prefix) = row.first_field {
output.push_str(&format!("{prefix:#} "));
}
output.push_str(&format!("{:#}\n", row.content));
}
println!("{output}");
Ok(())
}Detailed comparison
However, this does not deny the value of direct bib→csl translation; it merely indicates that this approach requires much more testing. |
|
Thanks for setting up those tests but this PR is in a very early state. I do not recommend wasting your time on tests just yet. At this point, this PR just marks what we have planned and to collect some input. Tbh, I'm surprised the PR works that well in your tests. I don't even consider parents of entries at the moment. I'll keep working on it and it will be a higher priority once #489 is merged. And to selfishly defend my approach here: I already find the new approach easier to manage. To write this PR, I had to look at the current state. Which means understanding the very complex biblatex -> Hayagriva translation and Hayagriva's CSL taxonomy and connect the two. |








Builds on #489.
This PR introduces direct translation from Biblatex entries to CSL variables. This offers more control over the taxonomy of CSL variables and hopefully loses less information than going the route of Biblatex -> hayagriva -> CSL.
Plan