fix(headings): digit-only lines do not define heading tiers (#166)
* fix(headings): digit-only lines do not define heading tiers A large bold page number (14pt folio over 11pt body) claimed tier 0: every real heading demoted one level document-wide, and the bold-size fallback (which requires an empty tier list) was blocked for documents whose headings match body size. Bench-neutral (MHS scores relative hierarchy); pdf-evals: 18 docs get their heading levels back (#### -> ###), semantic composite +0.0006, no percentile down. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(headings): exclude digit-only lines from the bold fallback tier pass too The exclusion in the main pass wasn't enough: with the page-number tier gone, the bold fallback re-collected the same bold folio. Also regenerates the thermo-freon12 snapshot (cosmetic churn on the scrambled legend fixture). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c908e33b39
commit
0f898a18fb
@@ -374,6 +374,15 @@ pub(crate) fn compute_heading_tiers(lines: &[TextLine], base_size: f32) -> Vec<f
|
|||||||
for line in lines {
|
for line in lines {
|
||||||
if let Some(first) = line.items.first() {
|
if let Some(first) = line.items.first() {
|
||||||
if first.font_size / base_size >= 1.2 {
|
if first.font_size / base_size >= 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);
|
heading_sizes.push(first.font_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,6 +407,11 @@ pub(crate) fn compute_heading_tiers(lines: &[TextLine], base_size: f32) -> Vec<f
|
|||||||
if tiers.is_empty() {
|
if tiers.is_empty() {
|
||||||
let mut bold_sizes: Vec<f32> = lines
|
let mut bold_sizes: Vec<f32> = lines
|
||||||
.iter()
|
.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_map(|line| line.items.first())
|
||||||
.filter(|it| it.is_bold && it.font_size / base_size >= 1.05)
|
.filter(|it| it.is_bold && it.font_size / base_size >= 1.05)
|
||||||
.map(|it| it.font_size)
|
.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]
|
#[test]
|
||||||
fn bold_fallback_tiers_when_nothing_clears_ratio_gate() {
|
fn bold_fallback_tiers_when_nothing_clears_ratio_gate() {
|
||||||
// 10pt body, 11pt bold section headings (book-style): no size clears
|
// 10pt body, 11pt bold section headings (book-style): no size clears
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
|
|
||||||
#### Thermodynamic Properties
|
#### Thermodynamic Properties
|
||||||
|
|
||||||
**of**
|
**of** ®
|
||||||
|
|
||||||
®
|
|
||||||
|
|
||||||
# Freon 12
|
# Freon 12
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user