mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-24 10:16:59 -06:00
A page named twice in an export list is exported once (found while probing)
The same selection written two ways gave different files:
file.exportPdf {"pages": "2,2"} → 1 page
file.exportPdf {"pages": [2, 2]} → 2 pages, the second a copy
file.exportPdf {"pages": [2,2,2]} → 3 pages
`parse_page_range` keeps the first of a repeat (`"2-2,2"` is one page too); the
array form appended whatever it was given. A list says which pages to export,
not how many times, so the array now drops a repeat as the string does. Both
`file.exportPdf` and `file.exportPptx` read the same parameter.
The test pins the agreement between the two forms over nine lists, in PDF and
PPTX, and the two facts I measured while checking it: the pages come out in the
document's order whichever order the list names them in, and `[2, 2]` is now
byte for byte the file `"2"` gives. A page that does not exist is still
refused, and an empty list still exports nothing.
Not from a ticket: I found it probing the page-range parameter.
This commit is contained in:
@@ -331,7 +331,12 @@ fn pages_param(id: &str, p: &Value, page_count: usize) -> Result<Option<Vec<usiz
|
||||
.and_then(|n| usize::try_from(n).ok())
|
||||
.filter(|n| *n >= 1 && *n <= page_count)
|
||||
.ok_or_else(|| bad(id, format!("bad page {x}")))?;
|
||||
v.push(n - 1);
|
||||
// A page named twice is one page, as `"2,2"` already is: the list says which
|
||||
// pages to export, not how many times. `[2, 2]` exported two copies of page 2
|
||||
// while `"2,2"` exported one.
|
||||
if !v.contains(&(n - 1)) {
|
||||
v.push(n - 1);
|
||||
}
|
||||
}
|
||||
Some(v)
|
||||
}
|
||||
@@ -1326,3 +1331,52 @@ mod pptx_tests {
|
||||
assert!(x.contains("<p:pic>") && !x.contains("prst=\"ellipse\""), "{x}");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod page_list_tests {
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::Session;
|
||||
|
||||
fn doc(pages: u64) -> Session {
|
||||
let mut s = Session::new();
|
||||
s.execute("file.new", &json!({"width": 200, "height": 200, "pages": pages, "facingPages": false, "margins": 0})).unwrap();
|
||||
s
|
||||
}
|
||||
|
||||
/// The same selection written two ways exported different files: `"2,2"` is one page, because
|
||||
/// `parse_page_range` keeps the first of a repeat, while `[2, 2]` was two copies of page 2.
|
||||
/// The list says which pages to export, not how many times.
|
||||
#[test]
|
||||
fn a_page_named_twice_is_exported_once_either_way() {
|
||||
let mut s = doc(4);
|
||||
for (pages, want) in [
|
||||
(json!("2,2"), 1),
|
||||
(json!([2, 2]), 1),
|
||||
(json!([2, 2, 2]), 1),
|
||||
(json!("2-2,2"), 1),
|
||||
(json!([1, 2, 1]), 2),
|
||||
(json!("1,2,1"), 2),
|
||||
(json!([4, 1]), 2),
|
||||
(json!("4,1"), 2),
|
||||
(json!("all"), 4),
|
||||
] {
|
||||
let r = s.execute("file.exportPdf", &json!({"pages": pages.clone()})).unwrap();
|
||||
assert_eq!(r["pages"].as_u64(), Some(want), "pdf {pages}");
|
||||
let r = s.execute("file.exportPptx", &json!({"pages": pages.clone()})).unwrap();
|
||||
assert_eq!(r["slides"].as_u64(), Some(want), "pptx {pages}");
|
||||
}
|
||||
// The two forms now agree byte for byte, and the pages come out in the document's order
|
||||
// whichever order the list names them in (which is how the export already behaved).
|
||||
let mut file = |pages: Value| {
|
||||
let r = s.execute("file.exportPdf", &json!({"pages": pages})).unwrap();
|
||||
r["base64"].as_str().unwrap_or_default().to_string()
|
||||
};
|
||||
assert_eq!(file(json!([4, 1])), file(json!("4,1")), "the array and the string agree");
|
||||
assert_eq!(file(json!([4, 1])), file(json!([1, 4])), "pages 1 and 4, in the document's order");
|
||||
assert_eq!(file(json!([2, 2])), file(json!("2")), "a repeat is the single page");
|
||||
// A page that does not exist is still refused, and an empty list still exports nothing.
|
||||
assert!(s.execute("file.exportPdf", &json!({"pages": [5]})).is_err());
|
||||
assert!(s.execute("file.exportPdf", &json!({"pages": []})).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user