rustypaper 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. {rustypaper-0.2.0 → rustypaper-0.2.1}/Cargo.lock +2 -2
  2. {rustypaper-0.2.0 → rustypaper-0.2.1}/Cargo.toml +2 -2
  3. {rustypaper-0.2.0 → rustypaper-0.2.1}/PKG-INFO +2 -2
  4. {rustypaper-0.2.0/rustypaper → rustypaper-0.2.1}/README.md +1 -1
  5. {rustypaper-0.2.0 → rustypaper-0.2.1}/pyproject.toml +1 -1
  6. {rustypaper-0.2.0 → rustypaper-0.2.1/rustypaper}/README.md +1 -1
  7. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/text/lines.rs +51 -3
  8. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/Cargo.toml +0 -0
  9. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/__init__.py +0 -0
  10. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/examples/ingest_share.rs +0 -0
  11. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/backend/mod.rs +0 -0
  12. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/backend/rustium.rs +0 -0
  13. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/compress.rs +0 -0
  14. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/doc.rs +0 -0
  15. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/emit/markdown.rs +0 -0
  16. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/emit/mod.rs +0 -0
  17. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/emit/text.rs +0 -0
  18. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/emit/typst.rs +0 -0
  19. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/error.rs +0 -0
  20. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/figure.rs +0 -0
  21. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/ir.rs +0 -0
  22. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/layout/columns.rs +0 -0
  23. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/layout/furniture.rs +0 -0
  24. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/layout/mod.rs +0 -0
  25. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/layout/order.rs +0 -0
  26. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/layout/stats.rs +0 -0
  27. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/lib.rs +0 -0
  28. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/main.rs +0 -0
  29. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/math/build.rs +0 -0
  30. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/math/latex.rs +0 -0
  31. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/math/mod.rs +0 -0
  32. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/math/symbols.rs +0 -0
  33. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/pipeline.rs +0 -0
  34. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/refs.rs +0 -0
  35. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/table.rs +0 -0
  36. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/text/mod.rs +0 -0
  37. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/text/vocab.rs +0 -0
  38. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/src/util.rs +0 -0
  39. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/tests/cli.rs +0 -0
  40. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper/tests/robustness.rs +0 -0
  41. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper-py/Cargo.toml +0 -0
  42. {rustypaper-0.2.0 → rustypaper-0.2.1}/rustypaper-py/src/lib.rs +0 -0
@@ -567,7 +567,7 @@ dependencies = [
567
567
 
568
568
  [[package]]
569
569
  name = "rustypaper"
570
- version = "0.2.0"
570
+ version = "0.2.1"
571
571
  dependencies = [
572
572
  "anyhow",
573
573
  "clap",
@@ -580,7 +580,7 @@ dependencies = [
580
580
 
581
581
  [[package]]
582
582
  name = "rustypaper-py"
583
- version = "0.2.0"
583
+ version = "0.2.1"
584
584
  dependencies = [
585
585
  "pyo3",
586
586
  "rustypaper",
@@ -3,14 +3,14 @@ resolver = "2"
3
3
  members = ["rustypaper", "rustypaper-py"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.0"
6
+ version = "0.2.1"
7
7
  edition = "2021"
8
8
  rust-version = "1.94"
9
9
  license = "MIT OR Apache-2.0"
10
10
  repository = "https://github.com/pgarrett-scripps/rustypaper"
11
11
 
12
12
  [workspace.dependencies]
13
- rustypaper = { path = "rustypaper", version = "0.2.0" }
13
+ rustypaper = { path = "rustypaper", version = "0.2.1" }
14
14
  # The pure-Rust PDF backend, from the registry. Deliberately not a path dependency: a path
15
15
  # only resolves where the sibling checkout happens to exist, which is this machine and not a
16
16
  # CI runner, and `cargo fmt --all` walks into it whether it is there or not. To develop the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rustypaper
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Topic :: Text Processing :: Markup
6
6
  Classifier: Topic :: Scientific/Engineering
@@ -32,7 +32,7 @@ cargo install rustypaper # the command-line tool
32
32
  ```
33
33
 
34
34
  ```toml
35
- rustypaper = "0.1" # the library
35
+ rustypaper = "0.2" # the library
36
36
  ```
37
37
 
38
38
  ```sh
@@ -19,7 +19,7 @@ cargo install rustypaper # the command-line tool
19
19
  ```
20
20
 
21
21
  ```toml
22
- rustypaper = "0.1" # the library
22
+ rustypaper = "0.2" # the library
23
23
  ```
24
24
 
25
25
  ```sh
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rustypaper"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Structure-aware conversion of born-digital scientific PDFs to Markdown, Typst and JSON."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -19,7 +19,7 @@ cargo install rustypaper # the command-line tool
19
19
  ```
20
20
 
21
21
  ```toml
22
- rustypaper = "0.1" # the library
22
+ rustypaper = "0.2" # the library
23
23
  ```
24
24
 
25
25
  ```sh
@@ -544,14 +544,33 @@ pub fn split_at_gutters(page: &PageRaw, lines: Vec<Line>, gutters: &[(f32, f32)]
544
544
 
545
545
  let mut out = Vec::with_capacity(lines.len());
546
546
  for line in lines {
547
+ let prose = line
548
+ .words
549
+ .iter()
550
+ .filter(|word| {
551
+ let text = word.text.trim_matches(|c: char| c.is_ascii_punctuation());
552
+ text.chars().count() >= 3 && text.chars().all(char::is_alphabetic)
553
+ })
554
+ .count()
555
+ >= 4;
547
556
  let mut current: Vec<Placed> = Vec::new();
548
557
  let mut pieces: Vec<Vec<Placed>> = Vec::new();
549
558
 
550
559
  for placed in line.glyphs {
551
- let x = page.glyphs[placed.index].bbox.center_x();
560
+ let bbox = page.glyphs[placed.index].bbox;
552
561
  let crossed = current.last().is_some_and(|prev| {
553
- let px = page.glyphs[prev.index].bbox.center_x();
554
- gutters.iter().any(|&(g0, g1)| px < g0 && x > g1)
562
+ let previous = page.glyphs[prev.index].bbox;
563
+ // Sparse coverage can include a ragged column edge. A wide gap
564
+ // across the center is additional evidence for prose only.
565
+ // Equations retain the stricter requirement to span the band.
566
+ gutters.iter().any(|&(g0, g1)| {
567
+ let center = (g0 + g1) * 0.5;
568
+ (previous.center_x() < g0 && bbox.center_x() > g1)
569
+ || (prose
570
+ && previous.x1 <= center
571
+ && bbox.x0 >= center
572
+ && bbox.x0 - previous.x1 >= line.size * 2.0)
573
+ })
555
574
  });
556
575
  if crossed && !current.is_empty() {
557
576
  pieces.push(std::mem::take(&mut current));
@@ -963,6 +982,35 @@ mod tests {
963
982
  assert!(split[0].bbox.x1 < split[1].bbox.x0);
964
983
  }
965
984
 
985
+ #[test]
986
+ fn a_ragged_column_edge_can_enter_the_coverage_band() {
987
+ let mut glyphs = run("the left column ends here", 160.0, 100.0, 10.0);
988
+ glyphs.extend(run("the right column starts here", 320.0, 100.0, 10.0));
989
+ let page = page_of(glyphs);
990
+ let split = split_at_gutters(&page, build_lines(&page), &[(255.0, 318.0)]);
991
+ assert_eq!(split.len(), 2);
992
+ assert_eq!(split[0].text(), "the left column ends here");
993
+ assert_eq!(split[1].text(), "the right column starts here");
994
+ }
995
+
996
+ #[test]
997
+ fn ordinary_word_spacing_across_a_gutter_keeps_a_full_width_line() {
998
+ let mut glyphs = run("left", 265.0, 100.0, 10.0);
999
+ glyphs.extend(run("right", 289.0, 100.0, 10.0));
1000
+ let page = page_of(glyphs);
1001
+ let split = split_at_gutters(&page, build_lines(&page), &[(255.0, 318.0)]);
1002
+ assert_eq!(split.len(), 1);
1003
+ }
1004
+
1005
+ #[test]
1006
+ fn mathematical_terms_do_not_count_as_prose_across_a_sparse_band() {
1007
+ let mut glyphs = run("alpha+1 beta+2 gamma+3 delta+4", 140.0, 100.0, 10.0);
1008
+ glyphs.extend(run("epsilon+5", 320.0, 100.0, 10.0));
1009
+ let page = page_of(glyphs);
1010
+ let split = split_at_gutters(&page, build_lines(&page), &[(255.0, 318.0)]);
1011
+ assert_eq!(split.len(), 1);
1012
+ }
1013
+
966
1014
  /// Lays out `\IEEEPARstart`: an initial two lines deep in the margin, the two lines it rises
967
1015
  /// through indented past it, and the paragraph then running to the full measure.
968
1016
  fn drop_capital_paragraph(initial: char) -> Vec<Glyph> {