mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-12 17:31:35 +00:00
fix(a11y): collect a structure element once whatever generation references it
The structure collector deduplicated by full reference while object lookup goes by number, so 3 0 R, 3 1 R, 3 2 R… each cloned the same element and its children again.
This commit is contained in:
1 parent
14ae839a28
commit
7f381eb494
2 files changed
+19
-1
No files matched your search
@@ -99,7 +99,9 @@ pub(crate) fn elements(doc: &Document) -> Vec<Element> {
|
||||
match k {
|
||||
Object::Array(a) => stack.extend(a.into_iter().rev().map(|x| (x, pg, parent, depth))),
|
||||
Object::Ref(r) => {
|
||||
if !seen.insert(r) {
|
||||
// By number: objects are looked up by number, so `4 1 R` is `4 0 R` again, and
|
||||
// must not be collected (with its children) once per generation written.
|
||||
if !seen.insert(r.num) {
|
||||
continue;
|
||||
}
|
||||
let Some(d) = doc.get(r).as_dict().cloned() else { continue };
|
||||
|
||||
@@ -1504,3 +1504,19 @@ fn marking_a_tag_artifact_refuses_content_past_the_decode_budget() {
|
||||
assert_eq!(mark_tag_artifact(&mut doc, ObjRef::new(7, 0)), Err(ArtifactError::TooLarge));
|
||||
assert_eq!(doc.get(ObjRef::new(3, 0)).as_dict().unwrap().get(b"Contents"), Some(&contents), "the page keeps its content");
|
||||
}
|
||||
|
||||
/// One structure element referenced under several generations is collected once: lookup goes by
|
||||
/// object number, so each alias would otherwise copy the element and its children again.
|
||||
#[test]
|
||||
fn a_structure_element_under_many_generations_is_collected_once() {
|
||||
let aliases: String = (0..200).map(|g| format!(" 3 {g} R")).collect();
|
||||
let doc = pdf(
|
||||
&[
|
||||
"<< /Type /Catalog /StructTreeRoot 2 0 R >>".into(),
|
||||
format!("<< /Type /StructTreeRoot /K [{aliases}] >>"),
|
||||
format!("<< /S /Figure /Alt (x) /K [{aliases}] >>"),
|
||||
],
|
||||
"",
|
||||
);
|
||||
assert_eq!(crate::alt::elements(&doc).len(), 1);
|
||||
}
|
||||
Reference in new issue
Block a user