Data merge: a QR field at a text insertion point is refused instead of written as text

Insert Field with a QR column and the text cursor in a frame added a text placeholder, so a merge wrote the QR payload as plain text. It now returns "qr placeholders bind to a frame" and leaves the story unchanged.
This commit is contained in:
dotCooCoo committed 2026-11-11 18:14:15 -08:00
1 parent e362820bc4
commit d490e0fb18
3 files changed
+21 -3

No files matched your search

+3
View File
@@ -503,6 +503,9 @@ fn add_placeholder(d: &mut Document, sel: &Selection, p: &Value, name: &str) ->
} else if field.kind == DataFieldKind::Image {
// An image field at the insertion point places the image inline in the text.
PlaceholderRole::Image
} else if field.kind == DataFieldKind::Qr {
// A QR field at the insertion point is refused below: QR codes bind to a frame.
PlaceholderRole::Qr
} else {
PlaceholderRole::Text
};
+14
View File
@@ -817,6 +817,20 @@ fn an_image_field_at_the_insertion_point_merges_as_an_inline_image() {
assert!((wide.1 - width).abs() < 0.01 && (wide.2 - width / 8.0).abs() < 0.01, "a wide image is scaled down to the frame: {wide:?}");
}
/// A QR field at a text insertion point is refused instead of merging its payload as text.
#[test]
fn a_qr_field_at_the_insertion_point_is_refused() {
let mut s = Session::new();
new_doc(&mut s, 1);
select_csv(&mut s, "@Photo,#Code\n/x.png,hello\n");
let made = text_frame(&mut s, [36.0, 36.0, 300.0, 300.0], "Hi ", None);
exec(&mut s, "text.select", json!({"story": made["story"], "anchor": 3, "focus": 3}));
let msg = err(&mut s, "data.placeholder.add", json!({"field": "Code"}));
assert!(msg.contains("bind to a frame"), "{msg}");
assert_eq!(texts(&s), vec!["Hi ".to_string()]);
assert!(s.documents()[0].doc.data_merge.placeholders.is_empty());
}
/// A typed `<<name>>` marker for an image column places the image too, from an absolute path;
/// an explicit text role still writes the path as text.
#[test]
+4 -3
View File
@@ -90,9 +90,10 @@ external PDF/X certification.
`data.source.remove` drops it); `data.fields` lists its fields. `data.placeholder.add {field, role?, story?, at?, end?, item?}`
marks text or a frame as a field (`role`: text, image, qr, hyperlink). An image field (a `@` column) inserted at a text
insertion point, or typed there as `<<name>>`, merges as an inline image at its natural size, scaled down to fit the
frame. An image path is absolute or relative to the data file's folder, then the document's; a path that starts with
one separator (`\Photos\a.jpg`) is tried from the drive's root first. `data.options` sets records, tiling and image
fitting; `data.preview {record}` / `data.preview.stop` show one record without saving it.
frame. A QR field (a `#` column) inserted at a text insertion point is refused; bind it to a frame instead. An image
path is absolute or relative to the data file's folder, then the document's; a path that starts with one separator
(`\Photos\a.jpg`) is tried from the drive's root first. `data.options` sets records, tiling and image fitting;
`data.preview {record}` / `data.preview.stop` show one record without saving it.
`data.merge` now **creates a new document** and leaves the template unchanged (the old `spread` parameter, which
appended pages to the template, is an error). It uses the linked source, or inline `csv` / `rows` / `path` / `bytes`: