diff --git a/src/markdown/analysis.rs b/src/markdown/analysis.rs index 1ffdfca..e4ac2c8 100644 --- a/src/markdown/analysis.rs +++ b/src/markdown/analysis.rs @@ -374,6 +374,15 @@ pub(crate) fn compute_heading_tiers(lines: &[TextLine], base_size: f32) -> Vec= 1.2 { + // Digit-only lines (page numbers, issue numbers) must not + // define heading tiers: a large bold folio claims tier 0 and + // blocks the bold-size fallback for the document's real + // same-size headings. + let text = line.text(); + let t = text.trim(); + if !t.is_empty() && t.chars().all(|c| !c.is_alphabetic()) { + continue; + } heading_sizes.push(first.font_size); } } @@ -398,6 +407,11 @@ pub(crate) fn compute_heading_tiers(lines: &[TextLine], base_size: f32) -> Vec = lines .iter() + .filter(|line| { + let text = line.text(); + let t = text.trim(); + !t.is_empty() && t.chars().any(|c| c.is_alphabetic()) + }) .filter_map(|line| line.items.first()) .filter(|it| it.is_bold && it.font_size / base_size >= 1.05) .map(|it| it.font_size) @@ -508,6 +522,19 @@ mod tests { } } + #[test] + fn digit_only_lines_do_not_define_tiers() { + // A 14pt bold page number must not claim tier 0 — that both demotes + // every real heading a level and blocks the bold-size fallback. + let lines = vec![ + line_of("76", 14.0, true, 760.0), + line_of("Replace", 11.0, true, 700.0), + line_of("body text at eleven points", 11.0, false, 680.0), + ]; + let tiers = compute_heading_tiers(&lines, 11.0); + assert!(tiers.is_empty(), "page number claimed a tier: {tiers:?}"); + } + #[test] fn bold_fallback_tiers_when_nothing_clears_ratio_gate() { // 10pt body, 11pt bold section headings (book-style): no size clears diff --git a/tests/snapshots/thermo-freon12.md b/tests/snapshots/thermo-freon12.md index bbf72e7..58c94eb 100644 --- a/tests/snapshots/thermo-freon12.md +++ b/tests/snapshots/thermo-freon12.md @@ -6,9 +6,7 @@ #### Thermodynamic Properties -**of** - -® +**of** ® # Freon 12