mirror of
https://github.com/storytold/wordcraft.git
synced 2026-11-06 18:51:26 +00:00
M-ODT gap 19: password, number, time and grid form controls kept
Controls of kinds WordCraft doesn't model (ODF 1.3 §13.5) were dropped with their place in the text; they are kept verbatim as buttons and image controls are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GBVQLyDnrG8Tn1yDQcUabC
This commit is contained in:
4 files changed
+48
-8
No files matched your search
@@ -21,9 +21,23 @@ const MAX_VALUE: usize = 10_000;
|
||||
pub(in crate::odt) const RADIO_ON: char = '\u{25C9}';
|
||||
pub(in crate::odt) const RADIO_OFF: char = '\u{25CB}';
|
||||
|
||||
/// Form controls WordCraft has no kind for, kept verbatim (see [`ContentControl::form_xml`]).
|
||||
const KEPT: [&str; 8] =
|
||||
["form:button", "form:image", "form:fixed-text", "form:file", "form:value-range", "form:frame", "form:image-frame", "form:generic-control"];
|
||||
/// Form controls WordCraft has no kind for, kept verbatim (see [`ContentControl::form_xml`]):
|
||||
/// every control of ODF 1.3 §13.5 but those it reads (text fields and areas, check boxes, option
|
||||
/// buttons, list and combo boxes, date fields) and hidden ones (kept apart).
|
||||
const KEPT: [&str; 12] = [
|
||||
"form:button",
|
||||
"form:image",
|
||||
"form:fixed-text",
|
||||
"form:file",
|
||||
"form:value-range",
|
||||
"form:frame",
|
||||
"form:image-frame",
|
||||
"form:generic-control",
|
||||
"form:password",
|
||||
"form:number",
|
||||
"form:time",
|
||||
"form:grid",
|
||||
];
|
||||
/// Most bytes of a kept control's XML.
|
||||
const MAX_KEPT: usize = 64 * 1024;
|
||||
/// The namespace prefixes a kept control may use: those the content WordCraft writes declares.
|
||||
|
||||
@@ -221,3 +221,28 @@ fn controls_keep_their_place_on_the_line_and_a_text_area_its_lines() {
|
||||
let plain = entry(&export(&import(&package(&doc_xml(), None)).unwrap()).unwrap(), "content.xml");
|
||||
assert!(plain.contains(r#"style:vertical-pos="top" style:vertical-rel="baseline""#), "{plain}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn password_number_time_and_grid_controls_are_kept() {
|
||||
// ODF 1.3 §13.5 controls WordCraft has no kind for: kept as read, each in its place.
|
||||
let controls = r#"<form:password form:name="Secret" xml:id="p1" form:id="p1" form:echo-char="*"/><form:number form:name="Count" xml:id="n1" form:id="n1" form:value="3"/><form:time form:name="At" xml:id="t1" form:id="t1" form:value="10:30:00"/><form:grid form:name="Rows" xml:id="g1" form:id="g1"><form:column form:name="Col" form:label="Name"><form:text form:name="Cell"/></form:column></form:grid>"#;
|
||||
let anchor = |id: &str| format!(r#"<draw:control text:anchor-type="as-char" svg:width="1in" svg:height="0.3in" draw:control="{id}"/>"#);
|
||||
let content = format!(
|
||||
r#"<office:document-content {NS_T} {NS_F}><office:body><office:text><office:forms><form:form form:name="Form">{controls}</form:form></office:forms><text:p>Fill {} {} {} {}</text:p></office:text></office:body></office:document-content>"#,
|
||||
anchor("p1"),
|
||||
anchor("n1"),
|
||||
anchor("t1"),
|
||||
anchor("g1")
|
||||
);
|
||||
let saved = export(&import(&package(&content, None)).unwrap()).unwrap();
|
||||
let c = entry(&saved, "content.xml");
|
||||
for el in [r#"<form:password "#, r#"form:echo-char="*""#, "<form:number ", "<form:time ", "<form:grid ", "<form:column ", r#"form:label="Name""#]
|
||||
{
|
||||
assert!(c.contains(el), "{el}: {c}");
|
||||
}
|
||||
// Each in its place in the text, naming its control.
|
||||
assert_eq!(c.matches("<draw:control ").count(), 4, "{c}");
|
||||
// And again.
|
||||
let again = entry(&export(&import(&saved).unwrap()).unwrap(), "content.xml");
|
||||
assert!(again.contains("<form:password ") && again.contains("<form:grid ") && again.matches("<draw:control ").count() == 4, "{again}");
|
||||
}
|
||||
@@ -285,7 +285,7 @@ Custom document properties retain their bookmark link targets through DOCX saves
|
||||
| 2026-11-02 | trivial | ODT: a chart lost the look WordCraft doesn't model (its fonts and sizes, axis and grid lines) on save, written anew from WordCraft's chart. The chart object as read is kept (through drawing it again when it opens or is resized), and written back whole while the chart reads the same; an edited chart is written from WordCraft's chart as before. The chart documents round-trip pixel-identical (`charts::an_unchanged_chart_is_written_back_as_it_was_and_an_edited_one_anew`, `engine::tests::redrawing_a_chart_keeps_the_chart_as_read`). Found with LibreOffice's serif business letter: a text frame outlined by its drawn stroke (`draw:stroke`, no `fo:border`) lost its outline; it's the frame's line. A header or footer whose style states no height (or that has none) was 0 tall; it's LibreOffice's 0.5 cm (measured), so the text no longer moves up. The letter round-trips to 116 differing pixels (from 4,223) (`text_boxes::a_frames_drawn_stroke_is_its_line_when_it_has_no_border`, `headers::a_header_without_a_stated_height_is_half_a_centimetre`) |
|
||||
| 2026-11-02 | trivial | ODT, found with LibreOffice's agendas: saving wrote every table's first row as a header row (`table:table-header-rows`), repeated at the top of each page, because a table style's header row (on by default in Word's table look) was taken for Repeat as header row; a table crossing a page showed its first row twice. Only rows set to repeat are written so. The agendas round-trip to about 145 differing pixels (from 5,269 and 5,086), their text the same (`tables::only_rows_set_to_repeat_are_written_as_header_rows`) |
|
||||
| 2026-11-02 | trivial | ODT, found with LibreOffice's report templates and one-page résumé. A paragraph's padding on a side without a border (measured: LibreOffice gives it room) was dropped; it's kept, laid out (see layout-parity) and written back. Unequal columns (`style:column` `style:rel-width` and indents, on pages and sections) were made equal; they keep their widths, written back as shares, without the gap LibreOffice ignores them beside. Columns with no stated gap have none (it had been Word's 0.5 in). A paragraph starting a column (`fo:break-before="column"`) didn't; it starts with Word's column break, written back on the paragraph. The report templates round-trip to 0–11 differing pixels (from 9,600), the résumé to 24 (from 6,286) (`para_borders::padding_without_a_border_keeps_its_room`, `odt::tests::unequal_columns_keep_their_widths_and_columns_without_a_gap_have_none`, `odt::tests::a_paragraph_starting_a_column_starts_with_a_column_break`) |
|
||||
| 2026-11-04 | trivial | ODT element audit ([odt-element-audit.md](odt-element-audit.md)): every element of the ODF 1.3 schema against two corpora (365 files) and a document of our own for each a text document can hold that no file did. Found: index marks over text, plugins and floating frames weren't kept, and a form's data source was taken for a control; fixed. Left: password and grid form controls. |
|
||||
| 2026-11-04 | trivial | ODT element audit ([odt-element-audit.md](odt-element-audit.md)): every element of the ODF 1.3 schema against two corpora (365 files) and a document of our own for each a text document can hold that no file did. Found: index marks over text, plugins and floating frames weren't kept, a form's data source was taken for a control, and password, number, time and grid form controls were dropped; all kept now. |
|
||||
| 2026-11-04 | trivial | ODT, found in StarOffice's long specifications: a reference mark (§6.6.2 `text:reference-mark`, which `text:reference-ref` names) was written as a bookmark only, so references to it found nothing once its paragraph was written from the model; it is written as both (a reference mark over its text when it ends in the paragraph, else at a point). Lists without an `xml:id` (older files') are kept as read too, given one. |
|
||||
| 2026-11-04 | trivial | ODT, found checking 220 files from Microsoft Office, OpenOffice.org, StarOffice, Calligra, Lotus Symphony and others: a section hidden with `text:display="none"` showed its text once written without the section (ending in a list, or in a table's cell); what a hidden section holds is now hidden text, so it stays hidden whatever is written, and WordCraft hides it too. A top-level list whose items nobody edited is written as read whole (a label followed by a space, picture bullets, an unnumbered header: what a paragraph's own markup can't say), a list going on with it naming it; a section may begin or end with a list, which then breaks there. A damaged package's media type isn't shown in its error. Of the 220, 166 round-trip pixel-identical and 194 with the same text. |
|
||||
| 2026-11-03 | trivial | ODT, found checking files from other applications: a kept package part without a media type (LibreOffice's empty `Configurations2/accelerator/current.xml`, another application's file the manifest didn't list) was written without a manifest entry, and LibreOffice refused to open the saved file; every file written has its entry now (ODF 1.3 Part 2 §4.3), its media type empty as read. |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ODT element audit
|
||||
|
||||
> **Last reviewed:** 2026-11-04 · **Last updated:** 2026-11-04 · **Change:** minor (first version: every element of the ODF 1.3 schema against two corpora and a generated sample of each element never seen)
|
||||
> **Last reviewed:** 2026-11-04 · **Last updated:** 2026-11-04 · **Change:** trivial (password, number, time and grid form controls kept); previously minor (first version: every element of the ODF 1.3 schema against two corpora and a generated sample of each element never seen)
|
||||
|
||||
Every element the ODF 1.3 schema (OASIS, Part 3, RELAX NG) defines, checked against what WordCraft's ODT reader and writer do with it. The question for each: does a file holding it open, and does a save without edits keep it? (See [file-format-parity.md](file-format-parity.md) for what WordCraft models; markup it doesn't model is written back as read while unedited: [odf-interpretation.md](odf-interpretation.md).)
|
||||
|
||||
@@ -45,9 +45,9 @@ Each in a document of our own: it opens, saves without edits keeping it, and sav
|
||||
| `draw:image-map` | kept |
|
||||
| `draw:plugin` | kept |
|
||||
| `form:connection-resource` | kept |
|
||||
| `form:grid` | **dropped**: a control of a kind WordCraft doesn't model (see below) |
|
||||
| `form:grid` | kept (as read, with its columns; LibreOffice opens the saved file, though its PDF export of a grid control fails whenever a document has automatic styles, ours or its own) |
|
||||
| `form:list-value` | kept (the sample held none; a list box's values are kept with the form) |
|
||||
| `form:password` | **dropped**: a control of a kind WordCraft doesn't model (see below) |
|
||||
| `form:password` | kept (as read) |
|
||||
| `number:boolean-style` | kept |
|
||||
| `number:embedded-text` | kept |
|
||||
| `number:era` | kept |
|
||||
@@ -98,10 +98,10 @@ The check found these, each fixed with a test (see [file-format-parity.md](file-
|
||||
- Lists lost what a paragraph's markup can't say (a label followed by a space, picture bullets, an unnumbered header): unedited lists are now kept as read.
|
||||
- Styles of different families, and list styles, sharing a name overwrote each other among the definitions kept.
|
||||
- A form's data source (`form:connection-resource`) was taken for a control; index marks over text, plugins and floating frames weren't kept.
|
||||
- Password, number, time and grid form controls (ODF 1.3 §13.5), of kinds WordCraft doesn't model, were dropped; they are kept as read, in their place in the text, as buttons and image controls were.
|
||||
|
||||
## Left
|
||||
|
||||
- **Password and grid form controls** (`form:password`, `form:grid`): WordCraft models text fields and areas, buttons, check boxes, option buttons, list and combo boxes, date, formatted and file fields, labels, images and image frames, frames, value ranges, hidden and generic controls; a control of another kind is dropped, with its place in the text.
|
||||
- **A section inside a table's cell, or one starting or ending at a paragraph with a twin elsewhere** (an empty one): written from the model, its text hidden still when the section was.
|
||||
- **A paragraph showing a chart, a form control, a linked text box, or a comment or tracked change reaching into another paragraph**: written from the model, which keeps what WordCraft models of it.
|
||||
- **Calligra's page sequence** (`text:page-sequence`, a layout of fixed pages) and **numbered paragraphs** (`text:numbered-paragraph`): read as text, written from the model.
|
||||
@@ -112,3 +112,4 @@ The check found these, each fixed with a test (see [file-format-parity.md](file-
|
||||
| Date | Change | What |
|
||||
|---|---|---|
|
||||
| 2026-11-04 | minor | First version |
|
||||
| 2026-11-04 | trivial | Password, number, time and grid form controls kept |
|
||||
Reference in new issue
Block a user