Skip to content

Commit

Permalink
Fix formatting of collapsed numeric citations (typst#176)
Browse files Browse the repository at this point in the history
* Update preset styles

* Add failing test for typst#154

* Fix formatting of collapsed numeric citations

* Revert changes to archive

* Refactor collapse_items

* Replace collapse test with local version

* Remove styles/numeric.csl

* simplify test

* slightly improve collapse code

* remove redundant test import

* wrap comment at 80 columns
  • Loading branch information
bluebear94 authored and danilasar committed Dec 31, 2024
1 parent d5ea285 commit 05ed80e
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 21 deletions.
55 changes: 34 additions & 21 deletions src/csl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,32 +861,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 @@ -896,7 +912,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 @@ -919,18 +935,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 =====<<

0 comments on commit 05ed80e

Please sign in to comment.