mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
M12: a date is tried in the field's first pattern again only when its format refused it
This commit is contained in:
@@ -2534,13 +2534,16 @@ fn run_edit(doc: &mut pdfcraft_cos::Document, edit: &Edit, cx: &mut EditCtx) ->
|
||||
Some(js) => pdfcraft_forms::set_value_with(doc, name, value, js),
|
||||
None => pdfcraft_forms::set_value(doc, name, value),
|
||||
};
|
||||
if let Err(refused) = set(doc, value) {
|
||||
// A date the field's pattern doesn't read may be typed by another of an XFA date
|
||||
// field's patterns: it is kept in the first.
|
||||
match xfa::typed_date(doc, cx.xfa.as_deref(), name, value) {
|
||||
match set(doc, value) {
|
||||
Ok(()) => {}
|
||||
// A date the field's format doesn't read may be typed by another of an XFA date
|
||||
// field's patterns: it is kept in the first. Only a format refusal is tried
|
||||
// again: it comes before any of the field's scripts run, so they run once.
|
||||
Err(refused @ pdfcraft_forms::FormError::Format(_)) => match xfa::typed_date(doc, cx.xfa.as_deref(), name, value) {
|
||||
Some(typed) => set(doc, &typed)?,
|
||||
None => return Err(refused.into()),
|
||||
}
|
||||
},
|
||||
Err(refused) => return Err(refused.into()),
|
||||
}
|
||||
}
|
||||
Edit::ApplyScriptChanges { changes } => match cx.js.as_mut() {
|
||||
|
||||
@@ -7305,3 +7305,21 @@ fn a_date_typed_by_another_of_an_xfa_fields_edit_patterns_is_kept_in_its_first()
|
||||
let data = pdfcraft_xfa::parse_datasets(&pdfcraft_xfa::read_packets(&cos).unwrap().unwrap().xdp).expect("a datasets packet");
|
||||
assert_eq!(data.text_at(&pdfcraft_xfa::som_to_path("form[0].leave[0]")), Some("2026-11-08"));
|
||||
}
|
||||
|
||||
/// A date the field's own scripts refuse is not tried again in another of an XFA date field's
|
||||
/// patterns: only a date its format refuses is, which happens before any script runs, so the
|
||||
/// scripts run once. This validate script counts its runs in `name` and accepts on its second.
|
||||
#[test]
|
||||
fn a_date_its_validate_script_refuses_is_not_tried_again() {
|
||||
let mut s = Session::new();
|
||||
let id = s
|
||||
.open("dates.pdf", None, Arc::new(pdfcraft_xfa::fixtures::shell(&pdfcraft_xfa::fixtures::date_alternatives_template())), None)
|
||||
.expect("opens");
|
||||
let script = Some("var n = Number(getField('name').value || 0) + 1; getField('name').value = String(n); event.rc = n >= 2;".to_string());
|
||||
s.apply(id, Edit::SetFieldScript { name: "leave".into(), event: "validate".into(), script }).unwrap();
|
||||
let value = |s: &Session, n: &str| s.get(id).unwrap().form.iter().find(|f| f.name == n).unwrap().value.clone();
|
||||
// Its format reads 18OCT26, and so does its DDMMMYY pattern.
|
||||
let refused = s.apply(id, Edit::SetFieldValue { name: "leave".into(), value: FieldValue::Text("18OCT26".into()) });
|
||||
assert!(refused.is_err(), "the validate script refused it, once");
|
||||
assert!(value(&s, "name").is_empty(), "nothing the refused run changed is kept: {:?}", value(&s, "name"));
|
||||
}
|
||||
|
||||
@@ -48,6 +48,10 @@ pub enum FormError {
|
||||
ReadOnly(String),
|
||||
#[error("{0}")]
|
||||
Invalid(String),
|
||||
/// The value doesn't fit the field's format (its keystroke check refused it), which is
|
||||
/// checked before any of the field's scripts run.
|
||||
#[error("{0}")]
|
||||
Format(String),
|
||||
#[error("{0}")]
|
||||
Cos(#[from] pdfcraft_cos::CosError),
|
||||
}
|
||||
@@ -1044,7 +1048,7 @@ fn write_value(doc: &mut Document, f: &Field, value: &FieldValue, scripts: &mut
|
||||
return invalid(format!("{:?} takes at most {max} characters", f.name));
|
||||
}
|
||||
// Keystroke (on commit) and Validate, as Acrobat runs them before accepting a value.
|
||||
let t = &af::keystroke(&f.actions.format, &f.name, t).map_err(FormError::Invalid)?;
|
||||
let t = &af::keystroke(&f.actions.format, &f.name, t).map_err(FormError::Format)?;
|
||||
af::validate(&f.actions.validate, t).map_err(FormError::Invalid)?;
|
||||
let t = &scripting::accept(doc, f, t, scripts)?;
|
||||
doc.update_dict(f.obj, |d| {
|
||||
|
||||
@@ -1270,7 +1270,7 @@ fn formats_validation_and_calculations_run_like_acrobat() {
|
||||
// Keystroke and validation errors use Acrobat's messages and change nothing.
|
||||
assert_eq!(
|
||||
set_value(&mut doc, "Qty", &FieldValue::Text("lots".into())),
|
||||
Err(FormError::Invalid("The value entered does not match the format of the field [ Qty ]".into()))
|
||||
Err(FormError::Format("The value entered does not match the format of the field [ Qty ]".into()))
|
||||
);
|
||||
assert_eq!(
|
||||
set_value(&mut doc, "Qty", &FieldValue::Text("120".into())),
|
||||
|
||||
Reference in New Issue
Block a user