Skip to content

Commit 29c2d6e

Browse files
Fix number_LeadingZeros
1 parent f00986e commit 29c2d6e

6 files changed

Lines changed: 42 additions & 19 deletions

File tree

docs/file-format.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -540,10 +540,9 @@ range and contain only integers, but may contain negative numbers. Numeric varia
540540
page-range: S10-15 # Page S10 to 15
541541
```
542542

543-
Note that the prefix and suffix for a numeric variable should be non-numeric. If
544-
you specify a number with leading zeros or numeric suffix, then the whole variable
545-
will be interpreted as a [string](#string) instead. This improves the style for
546-
atypical page numbers like `011` and `11E201`.
543+
Note that if you specify a number with a numeric affix, the whole variable will
544+
be interpreted as a [string](#string) instead. This improves the style for
545+
atypical page numbers like `11E201`.
547546

548547
#### Unicode Language Identifier
549548

src/csl/rendering/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,10 @@ impl<T: EntryLike> Iterator for BranchConditionIter<'_, '_, T> {
11321132
self.ctx.resolve_number_variable(var),
11331133
Some(NumberVariableResult::Regular(MaybeTyped::Typed(_)))
11341134
),
1135+
Variable::Page(var) => matches!(
1136+
self.ctx.resolve_page_variable(var),
1137+
Some(MaybeTyped::Typed(_))
1138+
),
11351139
_ => false,
11361140
})
11371141
} else {

src/types/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,12 @@ mod tests {
552552
assert!(val.suffix.is_none());
553553
assert_eq!(&val.to_string(), "-5");
554554

555+
let val = Numeric::from_str("01").unwrap();
556+
assert!(val.value == NumericValue::Number(1));
557+
assert_eq!(val.prefix_str(), Some("0"));
558+
assert!(val.suffix.is_none());
559+
assert_eq!(&val.to_string(), "01");
560+
555561
let val = Numeric::from_str("1st").unwrap();
556562
assert!(val.value == NumericValue::Number(1));
557563
assert!(val.prefix.is_none());

src/types/numeric.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,18 @@ impl FromStr for Numeric {
247247
fn from_str(value: &str) -> Result<Self, Self::Err> {
248248
let mut s = Scanner::new(value);
249249
s.eat_whitespace();
250-
let prefix = s.eat_while(|c: char| !c.is_numeric() && c != '-');
250+
251+
let prefix = {
252+
// Eat non-numeric characters and leading zeros.
253+
let start = s.cursor();
254+
s.eat_while(|c: char| !c.is_numeric() && c != '-');
255+
let zeros = s.eat_while('0');
256+
if !zeros.is_empty() && s.peek().is_none_or(|c| !c.is_numeric()) {
257+
// Uneat the last zero if the value is just zero.
258+
s.uneat();
259+
}
260+
s.from(start)
261+
};
251262

252263
let value = number(&mut s).ok_or(NumericError::NoNumber)?;
253264
let space_after_value = s.eat_whitespace();
@@ -329,23 +340,18 @@ pub enum NumericError {
329340
MissingDelimiter,
330341
}
331342

332-
/// Eat a number from the scanner.
333-
/// The number can be positive, negative, or zero, but can't have leading zeros.
343+
/// Eat a number from the scanner, assuming leading whitespaces and zeros have
344+
/// already been eaten.
345+
///
346+
/// The number can be positive, negative, or zero.
334347
fn number(s: &mut Scanner) -> Option<i32> {
335-
let start = s.cursor();
336-
337348
let negative = s.eat_if('-');
338-
let leading_zero = s.eat_if('0');
339349
let num = s.eat_while(|c: char| c.is_numeric());
340-
341-
match (leading_zero, num.is_empty()) {
342-
(true, true) => Some(0),
343-
(false, false) => num.parse::<i32>().ok().map(|n| if negative { -n } else { n }),
344-
_ => {
345-
s.jump(start);
346-
None
347-
}
350+
if num.is_empty() {
351+
return None;
348352
}
353+
354+
num.parse::<i32>().ok().map(|n| if negative { -n } else { n })
349355
}
350356

351357
impl Display for Numeric {

src/types/page.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ mod test {
416416
#[test]
417417
fn nonnumeric_page() {
418418
// https://github.com/typst/hayagriva/issues/170
419-
for s in &["11E201", "072711", "1.1-1.36", "011-012"] {
419+
for s in &["11E201", "1.36"] {
420420
let n: MaybeTyped<PageRanges> = MaybeTyped::infallible_from_str(s);
421421
assert_eq!(n, MaybeTyped::String(s.to_string()));
422422
}
@@ -429,5 +429,12 @@ mod test {
429429
Numeric::from_str("15").unwrap(),
430430
)]))
431431
);
432+
assert_eq!(
433+
MaybeTyped::<PageRanges>::infallible_from_str("011-012"),
434+
MaybeTyped::Typed(PageRanges::new(vec![PageRangesPart::Range(
435+
Numeric::from_str("011").unwrap(),
436+
Numeric::from_str("012").unwrap(),
437+
)]))
438+
);
432439
}
433440
}

tests/citeproc-pass.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ nameorder_ShortNameAsSortDemoteNever
409409
namespaces_NonNada3
410410
number_FailingDelimiters
411411
number_IsNumericWithAlpha
412+
number_LeadingZeros
412413
number_MixedPageRange
413414
number_MixedText
414415
number_PageFirst

0 commit comments

Comments
 (0)