Use evaluated field values in the placed text so the PDF text layer shows the slide number (#1153)

This commit is contained in:
MarekSpodBiedry committed 2026-10-22 21:02:59 +02:00
1 parent a2435383b1
commit cc6773c95f
2 files changed
+30 -3

No files matched your search

+18 -3
View File
@@ -2,9 +2,9 @@
//! that put real text over a raster (PDF text layer, links) and for text extraction.
use deckcraft_model::resolve::{self, Ctx};
use deckcraft_model::text::{Hyperlink, TextBody};
use deckcraft_model::text::{Hyperlink, RunKind, TextBody};
use deckcraft_model::{Presentation, Shape, ShapeId, ShapeKind};
use deckcraft_text::{Opts, TextLayout};
use deckcraft_text::{Fields, Opts, TextLayout};
use kurbo::{Affine, Rect};
use crate::{SlideFields, shape_geometry, table};
@@ -162,7 +162,22 @@ fn place_text(out: &mut Placed, rctx: &Ctx, fields: &SlideFields, owner: ShapeId
let r = Rect::new(x0, line.top, x1, line.bottom);
out.links.push(PlacedLink { rect: m.transform_rect_bbox(r), link, shape: owner, text: true });
}
out.texts.push(PlacedText { layout, transform: m, body: body.clone() });
// Field runs carry their saved text (`‹#›`); the layout drew their values, so the body that
// goes with it (character offsets, text layer) must hold the same values.
let mut body = body.clone();
for para in &mut body.paragraphs {
let src = para.clone();
for run in &mut para.runs {
if let RunKind::Field { field } = &run.kind {
let lang = resolve::run(rctx, s, &src, &run.props).lang;
if let Some(v) = fields.field_in(field, lang.as_deref()) {
run.text = v;
run.kind = RunKind::Text;
}
}
}
}
out.texts.push(PlacedText { layout, transform: m, body });
}
/// The hyperlink of the model run containing character `at` of paragraph `para`.
+12
View File
@@ -2595,3 +2595,15 @@ fn empty_bullet_is_gray_only_while_editing_and_never_in_exports() {
assert!(changed.iter().any(|(px, _)| px[0] == 179 && px[1] == 179 && px[2] == 179));
assert!(changed.iter().all(|(px, _)| px[0] >= 179 && px[0] == px[1] && px[1] == px[2]));
}
#[test]
fn placed_text_holds_the_field_value_not_the_saved_placeholder() {
let mut p = deck_with(vec![field_shape(Some("slidenum"), "<#>")]);
let second = p.slides[0].clone();
p.slides.push(second);
let placed = place_slide(&p, 1);
assert_eq!(placed.texts.len(), 1);
assert_eq!(placed.texts[0].body.text(), "2");
// The layout was drawn from the same value, so the offsets agree with the body.
assert_eq!(placed.texts[0].layout.runs.iter().map(|r| r.chars.1).max(), Some(1));
}