Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix formatting of collapsed numeric citations #176

Merged
merged 11 commits into from
Aug 8, 2024
55 changes: 34 additions & 21 deletions src/csl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,32 +856,48 @@ fn find_ambiguous_sets<T: EntryLike + PartialEq>(
fn collapse_items<'a, T: EntryLike>(cite: &mut SpeculativeCiteRender<'a, '_, T>) {
let style = &cite.request.style;

let after_collapse_delim = style.citation.after_collapse_delimiter.as_deref();
let after_collapse_delim = style
.citation
.after_collapse_delimiter
.as_deref()
.or(style.citation.layout.delimiter.as_deref());

let group_delimiter = style.citation.cite_group_delimiter.as_deref();

match style.citation.collapse {
Some(Collapse::CitationNumber) => {
// Option with the start and end of the range.
let mut range_start: Option<(usize, usize)> = None;
let mut just_collapsed = false;

let end_range = |items: &mut [SpeculativeItemRender<'a, T>],
range_start: &mut Option<(usize, usize)>,
just_collapsed: &mut bool| {
let use_after_collapse_delim = *just_collapsed;
*just_collapsed = false;

if let &mut Some((start, end)) = range_start {
// If the previous citation range was collapsed, use the
// after-collapse delimiter before the next item.
if use_after_collapse_delim {
items[start].delim_override = after_collapse_delim;
}

let end_range =
|items: &mut [SpeculativeItemRender<'a, T>],
range_start: &mut Option<(usize, usize)>| {
if let &mut Some((start, end)) = range_start {
// There should be at least three items in the range.
if start + 1 < end {
items[end].delim_override =
after_collapse_delim.or(Some("–"));

for item in &mut items[start + 1..end] {
item.hidden = true;
}
// There should be at least three items in the range to
// collapse.
if start + 1 < end {
items[end].delim_override = Some("–");

for item in &mut items[start + 1..end] {
item.hidden = true;
}

*just_collapsed = true;
}
}

*range_start = None;
};
*range_start = None;
};

for i in 0..cite.items.len() {
let citation_number = {
Expand All @@ -891,7 +907,7 @@ fn collapse_items<'a, T: EntryLike>(cite: &mut SpeculativeCiteRender<'a, '_, T>)
if item.hidden
|| item.rendered.get_meta(ElemMeta::CitationNumber).is_none()
{
end_range(&mut cite.items, &mut range_start);
end_range(&mut cite.items, &mut range_start, &mut just_collapsed);
continue;
}

Expand All @@ -914,18 +930,15 @@ fn collapse_items<'a, T: EntryLike>(cite: &mut SpeculativeCiteRender<'a, '_, T>)
range_start = Some((start, i));
}
_ => {
end_range(&mut cite.items, &mut range_start);
end_range(&mut cite.items, &mut range_start, &mut just_collapsed);
range_start = Some((i, i));
}
}
}

end_range(&mut cite.items, &mut range_start);
end_range(&mut cite.items, &mut range_start, &mut just_collapsed);
}
Some(Collapse::Year | Collapse::YearSuffix | Collapse::YearSuffixRanged) => {
let after_collapse_delim =
after_collapse_delim.or(style.citation.layout.delimiter.as_deref());

// Index of where the current group started and the group we are
// currently in.
let mut group_idx: Option<(usize, usize)> = None;
Expand Down
154 changes: 154 additions & 0 deletions tests/local/collapse_CitationNumberRangesSeparated.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
>>===== MODE =====>>
citation
<<===== MODE =====<<

Simplified from collapse_CitationNumberRangesInsert.txt


>>===== RESULT =====>>
[1–8]
[1–3;5]
[4,6–8]
[2,3,6]
<<===== RESULT =====<<

>>===== CITATION-ITEMS =====>>
[
[
{
"id": "ITEM-1"
},
{
"id": "ITEM-2"
},
{
"id": "ITEM-3"
},
{
"id": "ITEM-4"
},
{
"id": "ITEM-5"
},
{
"id": "ITEM-6"
},
{
"id": "ITEM-7"
},
{
"id": "ITEM-8"
}
],
[
{
"id": "ITEM-1"
},
{
"id": "ITEM-2"
},
{
"id": "ITEM-3"
},
{
"id": "ITEM-5"
}
],
[
{
"id": "ITEM-4"
},
{
"id": "ITEM-6"
},
{
"id": "ITEM-7"
},
{
"id": "ITEM-8"
}
],
[
{
"id": "ITEM-2"
},
{
"id": "ITEM-3"
},
{
"id": "ITEM-6"
}
]
]
<<===== CITATION-ITEMS =====<<


>>===== CSL =====>>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0">
<info>
<id />
<title />
<updated>2009-08-10T04:49:00+09:00</updated>
</info>
<citation collapse="citation-number" after-collapse-delimiter=";">
<sort>
<key variable="author" />
<key variable="issued" />
</sort>
<layout prefix="[" suffix="]" delimiter=",">
<text variable="citation-number" />
</layout>
</citation>
</style>
<<===== CSL =====<<


>>===== INPUT =====>>
[
{
"id": "ITEM-1",
"title": "Paper 1",
"type": "book"
},
{
"id": "ITEM-2",
"title": "Paper 2",
"type": "book"
},
{
"id": "ITEM-3",
"title": "Paper 3",
"type": "book"
},
{
"id": "ITEM-4",
"title": "Paper 4",
"type": "book"
},
{
"id": "ITEM-5",
"title": "Paper 5",
"type": "book"
},
{
"id": "ITEM-6",
"title": "Paper 6",
"type": "book"
},
{
"id": "ITEM-7",
"title": "Paper 7",
"type": "book"
},
{
"id": "ITEM-8",
"title": "Paper 8",
"type": "book"
}
]
<<===== INPUT =====<<


>>===== VERSION =====>>
1.0
<<===== VERSION =====<<
Loading