Skip to content

Commit

Permalink
Add disambiguation to alphanumeric style (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
reknih authored Oct 10, 2024
1 parent 9e30220 commit 7be2efc
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 31 deletions.
2 changes: 1 addition & 1 deletion archive/styles/alphanumeric.cbor
Original file line number Diff line number Diff line change
@@ -1 +1 @@
�dinfo�fauthor��dnamekMartin Haugeemailumartin.haug@typst.app�dnamenLaurenz Mädjeeemailxlaurenz.maedje@typst.appkcontributor�hcategory��p@citation-formatelabelefield�bidx!http://typst.org/csl/alphanumericdissn�dlink�frights�e$textqMIT OR Apache-2.0gsummary�f$valuevAlphanumeric citationsetitle�f$valuelAlphanumerich@versionc1.0hcitation�dsort�ckey��i@variablefauthore@sortiascending�i@variablefissuede@sortiascendingflayout�f$value��dtext�i@variablencitation-labele@formdlongg@quotes�n@strip-periods��g@prefixa[g@suffixa]j@delimiterb, x@disambiguate-add-givenname�x@givenname-disambiguation-rulegby-citew@disambiguate-add-names�x@disambiguate-add-year-suffix�i@collapseocitation-numberx@after-collapse-delimiterb; s@near-note-distance�f@classgin-textw@initialize-with-hyphen�x@demote-non-dropping-particlepdisplay-and-sortemacro�flocale��
�dinfo�fauthor��dnamekMartin Haugeemailumartin.haug@typst.app�dnamenLaurenz Mädjeeemailxlaurenz.maedje@typst.appkcontributor�hcategory��p@citation-formatelabelefield�bidx!http://typst.org/csl/alphanumericdissn�dlink�frights�e$textqMIT OR Apache-2.0gsummary�f$valuevAlphanumeric citationsetitle�f$valuelAlphanumerich@versionc1.0hcitation�dsort�ckey��i@variablefauthore@sortiascending�i@variablefissuede@sortiascendingflayout�f$value��dtext�i@variablencitation-labele@formdlongg@quotes�n@strip-periods���dtext�i@variablekyear-suffixe@formdlongg@quotes�n@strip-periods��g@prefixa[g@suffixa]j@delimiterb, x@disambiguate-add-givenname�x@givenname-disambiguation-rulegby-citew@disambiguate-add-names�x@disambiguate-add-year-suffix�i@collapseocitation-numberx@after-collapse-delimiterb; s@near-note-distance�f@classgin-textw@initialize-with-hyphen�x@demote-non-dropping-particlepdisplay-and-sortemacro�flocale��
29 changes: 15 additions & 14 deletions src/csl/elem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ pub enum ElemMeta {
Name(NameVariable, usize),
/// The entry corresponds to a citation item.
Entry(usize),
/// The element is the output of `cs:text` with a `variable` set to
/// `citation-label`.
CitationLabel,
}

/// A container for element children with useful methods.
Expand All @@ -165,20 +168,18 @@ impl ElemChildren {

/// Retrieve a reference to the first child with a matching meta by
/// DFS.
pub fn get_meta(&self, meta: ElemMeta) -> Option<&Elem> {
for child in &self.0 {
match child {
ElemChild::Elem(e) if e.meta == Some(meta) => return Some(e),
ElemChild::Elem(e) => {
if let Some(e) = e.children.get_meta(meta) {
return Some(e);
}
}
_ => {}
}
}

None
pub fn find_meta(&self, meta: ElemMeta) -> Option<&Elem> {
self.find_elem_by(&|e| e.meta == Some(meta))
}

/// Retrieve a mutable reference to the first child matching the predicate
/// by DFS.
pub fn find_elem_by<F: Fn(&Elem) -> bool>(&self, f: &F) -> Option<&Elem> {
self.0.iter().find_map(|child| match child {
ElemChild::Elem(e) if f(e) => Some(e),
ElemChild::Elem(e) => e.children.find_elem_by(f),
_ => None,
})
}

/// Remove the first child with any meta by DFS.
Expand Down
97 changes: 82 additions & 15 deletions src/csl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ impl<'a, T: EntryLike + Hash + PartialEq + Eq + Debug> BibliographyDriver<'a, T>

let Some(name_elem) = cite.items[i]
.rendered
.get_meta(ElemMeta::Names)
.find_meta(ElemMeta::Names)
.map(|e| format!("{:?}", e))
else {
continue;
Expand Down Expand Up @@ -758,19 +758,32 @@ fn disambiguate_year_suffix<F, T>(
T: EntryLike + PartialEq,
F: FnMut(&T, DisambiguateState),
{
if renders
.iter()
.flat_map(|r| r.items.iter())
.any(|i| i.rendered.get_meta(ElemMeta::Date).is_some())
&& group.iter().any(|&(cite_idx, item_idx)| {
renders[cite_idx].request.style.citation.disambiguate_add_year_suffix
&& renders[cite_idx].items[item_idx]
.cite_props
.speculative
.disambiguation
.may_disambiguate_with_year_suffix()
})
{
if renders.iter().flat_map(|r| r.items.iter()).any(|i| {
let entry_has_date = i
.entry
.resolve_date_variable(DateVariable::Issued)
.or_else(|| i.entry.resolve_date_variable(DateVariable::Accessed))
.or_else(|| i.entry.resolve_date_variable(DateVariable::AvailableDate))
.or_else(|| i.entry.resolve_date_variable(DateVariable::EventDate))
.or_else(|| i.entry.resolve_date_variable(DateVariable::Submitted))
.or_else(|| i.entry.resolve_date_variable(DateVariable::OriginalDate))
.is_some();

i.rendered
.find_elem_by(&|e| {
// The citation label will contain the date if there is one.
e.meta == Some(ElemMeta::Date)
|| (entry_has_date && e.meta == Some(ElemMeta::CitationLabel))
})
.is_some()
}) && group.iter().any(|&(cite_idx, item_idx)| {
renders[cite_idx].request.style.citation.disambiguate_add_year_suffix
&& renders[cite_idx].items[item_idx]
.cite_props
.speculative
.disambiguation
.may_disambiguate_with_year_suffix()
}) {
let mut entries = Vec::new();
for &(cite_idx, item_idx) in group.iter() {
let item = &renders[cite_idx].items[item_idx];
Expand Down Expand Up @@ -905,7 +918,7 @@ fn collapse_items<'a, T: EntryLike>(cite: &mut SpeculativeCiteRender<'a, '_, T>)
// cannot be mutably borrowed below otherwise.
let item = &cite.items[i];
if item.hidden
|| item.rendered.get_meta(ElemMeta::CitationNumber).is_none()
|| item.rendered.find_meta(ElemMeta::CitationNumber).is_none()
{
end_range(&mut cite.items, &mut range_start, &mut just_collapsed);
continue;
Expand Down Expand Up @@ -2887,4 +2900,58 @@ mod tests {
// }
}
}

#[test]
#[cfg(feature = "archive")]
fn test_alphanumeric_disambiguation() {
let bibtex = r#"@article{chenTransMorphTransformerUnsupervised2021,
title = {{{TransMorph}}: {{Transformer}} for Unsupervised Medical Image Registration},
author = {Chen, Junyu and Frey, Eric C. and He, Yufan and Segars, William P. and Li, Ye and Du, Yong},
date = {2021},
}
@article{chenViTVNetVisionTransformer2021,
title = {{{ViT-V-Net}}: {{Vision Transformer}} for {{Unsupervised Volumetric Medical Image Registration}}},
author = {Chen, Junyu and He, Yufan and Frey, Eric C. and Li, Ye and Du, Yong},
date = {2021},
}"#;

let library = crate::io::from_biblatex_str(bibtex).unwrap();
let alphanumeric = archive::ArchivedStyle::Alphanumeric.get();
let citationberg::Style::Independent(alphanumeric) = alphanumeric else {
unreachable!()
};

let mut driver = BibliographyDriver::new();
for entry in library.iter() {
driver.citation(CitationRequest::new(
vec![CitationItem::with_entry(entry)],
&alphanumeric,
None,
&[],
None,
));
}

let finished = driver.finish(BibliographyRequest {
style: &alphanumeric,
locale: None,
locale_files: &[],
});

let mut c1 = String::new();
let mut c2 = String::new();

finished.citations[0]
.citation
.write_buf(&mut c1, BufWriteFormat::Plain)
.unwrap();
finished.citations[1]
.citation
.write_buf(&mut c2, BufWriteFormat::Plain)
.unwrap();

assert_eq!(c1, "[Che+21a]");
assert_eq!(c2, "[Che+21b]");
}
}
5 changes: 5 additions & 0 deletions src/csl/rendering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ impl RenderCsl for citationberg::Text {
{
Some(ElemMeta::CitationNumber)
}
TextTarget::Variable { var, .. }
if var == StandardVariable::CitationLabel.into() =>
{
Some(ElemMeta::CitationLabel)
}
TextTarget::Variable { .. } => Some(ElemMeta::Text),
_ => None,
},
Expand Down
4 changes: 3 additions & 1 deletion styles/alphanumeric.csl
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
<rights>MIT OR Apache-2.0</rights>
<summary>Alphanumeric citations</summary>
</info>
<citation collapse="citation-number" after-collapse-delimiter="; ">
<citation collapse="citation-number" after-collapse-delimiter="; "
disambiguate-add-year-suffix="true">
<sort>
<key variable="author" />
<key variable="issued" />
</sort>
<layout prefix="[" suffix="]" delimiter=", ">
<text variable="citation-label" />
<text variable="year-suffix" />
</layout>
</citation>
</style>

0 comments on commit 7be2efc

Please sign in to comment.