Merge pull request #1091 from MMexicann/fix/empty-number-format-sections

# Conflicts:
#	crates/model/src/numfmt.rs
This commit is contained in:
Brandon Thomas
2026-10-23 17:11:13 -04:00
3 changed files with 38 additions and 1 deletions
+3
View File
@@ -4,6 +4,7 @@
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-23 · **Change:** trivial (progress log: scroll bars on the zoomed slide pane, #1157; previous: minor, native chart payloads stored in bounded ZIP members; previous: major, community PR wave 2026-10-14: ~60 landed items in the progress log, among them the Font, Paragraph, Photo Album, theme colour and font and Date and Time dialogs, presenter and show controls, the SmartArt Text Pane and PPTX corpus slices; breadth 84% after `cargo xtask parity`, ready stays ~55%, stage stays alpha; duplicated rows and headers folded; previous: minor, hours to ~95% per audience added) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-22 · **Change:** trivial (fill and outline edits reach group members, #1079; stage and scores unchanged) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-20 · **Change:** trivial (empty chart number-format sections hide values; previous: minor, native chart payloads stored in bounded ZIP members; previous: major, community PR wave 2026-10-14: ~60 landed items in the progress log, among them the Font, Paragraph, Photo Album, theme colour and font and Date and Time dialogs, presenter and show controls, the SmartArt Text Pane and PPTX corpus slices; breadth 84% after `cargo xtask parity`, ready stays ~55%, stage stays alpha; duplicated rows and headers folded; previous: minor, hours to ~95% per audience added) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
DeckCraft aims at full PowerPoint parity, and to be better: faster, open (a documented zip+JSON
format plus PPTX), scriptable by agents (CLI, JSON control channel, MCP), and available everywhere
@@ -142,6 +143,7 @@ app's JSON control channel (`deckcraft --control PORT`).
| 2026-10-23 | Normal view: a slide zoomed past the window gets a horizontal and a vertical scroll bar on the axes that overflow; drag the thumb or click the track to reach every edge (#1157) |
| 2026-10-22 | Shape Fill and Shape Outline format the members of a selected group, including nested groups, in one undo step. Fill transparency retains each member's effective colour (#1079) |
| 2026-10-21 | 3-D contours, extrusion depths and bevels keep their size in points inside a group whose child coordinates scale its shapes: a 1 pt contour on a small extruded cube in a legacy group drew hundreds of points wide, a band across the slide |
| 2026-10-20 | Chart number formats with explicit empty positive, negative or zero sections hide the corresponding labels, including all values with three semicolons; a blank whole format still uses General. Synthetic formatter regressions |
| 2026-10-18 | Native chart sidecar bytes move from JSON arrays into referenced ZIP entries, with shared media byte/item limits and bounded reads; older inline sidecars still load. Synthetic format regressions cover large workbooks and malformed members |
| 2026-10-18 | Slide thumbnails and the Slide Sorter render only the slides in view: on a deck of more than 600 slides they used to evict their own thumbnails, so the pane flashed white and never finished (#969) |
| 2026-10-18 | Resizing with the mouse snaps the edge being dragged to the slide, guides and other shapes: a fixed edge that already lined up used to take the snap and leave the dragged edge free, and a fixed edge near a line shifted the dragged one (#961) |
@@ -258,6 +260,7 @@ app's JSON control channel (`deckcraft --control PORT`).
|---|---|---|
| 2026-10-22 | trivial | Progress log: Animation Pane ▸ Play From. Scores unchanged |
| 2026-10-23 | trivial | Progress log: scroll bars on the zoomed slide pane (#1157). Scores and milestone names unchanged |
| 2026-10-20 | trivial | Explicit empty chart number-format sections hide their values; blank whole-code General fallback is retained. Synthetic formatter regressions; chart-element scores and readiness estimates unchanged |
| 2026-10-18 | minor | Native chart payloads use referenced ZIP members and share media byte/item limits; old inline sidecars remain readable. Synthetic tests cover multi-megabyte layout, all shape owners, shared budgets, missing/corrupt members and invalid references. Scores and milestone scope unchanged |
| 2026-10-15 | trivial | Progress log: chart package parts survive a native save. Scores and milestone names unchanged |
| 2026-10-18 | trivial | Progress log: thumbnails of huge decks render only the slides in view (#969) |
+31 -1
View File
@@ -158,7 +158,7 @@ pub fn format(code: &str, v: f64, lang: Option<&str>) -> String {
([pos, ..], v) => (*pos, v.abs(), v < 0.0),
([], v) => ("General", v.abs(), v < 0.0),
};
if sec.trim().eq_ignore_ascii_case("general") || sec.trim().is_empty() {
if sec.trim().eq_ignore_ascii_case("general") || (secs.len() == 1 && sec.trim().is_empty()) {
let s = general(v, dec);
return if minus { format!("-{s}") } else { s };
}
@@ -343,6 +343,36 @@ mod tests {
assert_eq!(format("0.00,\"K\"", 15_000.0, Some("en-US")), "15.00K");
}
#[test]
fn explicit_empty_sections_hide_their_values() {
for v in [3.0, -3.0, 0.0, -0.0] {
assert_eq!(format(";;;", v, None), "", "all sections empty: {v}");
}
for (code, positive, negative, zero) in [
(";0;0", "", "3", "0"),
("0;;0", "3", "", "0"),
("0;-0;", "3", "-3", ""),
(";0", "", "3", ""),
(r#"";"0;;"#, ";3", "", ""),
(r"\;0;;", ";3", "", ""),
] {
assert_eq!(format(code, 3.0, None), positive, "positive: {code}");
assert_eq!(format(code, -3.0, None), negative, "negative: {code}");
assert_eq!(format(code, 0.0, None), zero, "zero: {code}");
}
assert_eq!(format("0;-0;", -0.0, None), "");
}
#[test]
fn blank_whole_codes_and_general_keep_their_fallback() {
for code in ["", " \t", "General", " general "] {
assert_eq!(format(code, 2.5, None), "2.5", "{code:?}");
assert_eq!(format(code, -2.5, None), "-2.5", "{code:?}");
assert_eq!(format(code, 0.0, None), "0", "{code:?}");
assert_eq!(format(code, 2.5, Some("de-DE")), "2,5", "{code:?}");
}
}
#[test]
fn scientific_formats() {
assert_eq!(format("0.00E+00", 1234.0, None), "1.23E+03");
+4
View File
@@ -1,6 +1,7 @@
# Where DeckCraft falls short of PowerPoint
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-22 · **Change:** minor (Animation Pane ▸ Play From; previous: minor, native chart payloads stored in bounded ZIP members; previous: major, community PR wave 2026-10-14: soak tests, PPTX corpus, comment threads (#70), embedded fonts, SmartArt Text Pane, Animation Pane timeline, Hunspell spelling, thesaurus, AutoCorrect, 14 new dialogs, pen pressure and trackpad gestures; duplicated entries and headers folded; previous: minor, 3-D bevel, camera and face lighting rendered) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-20 · **Change:** trivial (empty chart number-format sections hide values; previous: minor, native chart payloads stored in bounded ZIP members; previous: major, community PR wave 2026-10-14: soak tests, PPTX corpus, comment threads (#70), embedded fonts, SmartArt Text Pane, Animation Pane timeline, Hunspell spelling, thesaurus, AutoCorrect, 14 new dialogs, pen pressure and trackpad gestures; duplicated entries and headers folded; previous: minor, 3-D bevel, camera and face lighting rendered) · **Target:** Microsoft PowerPoint for Mac 16.113 (Microsoft 365)
Every known shortfall, one entry each, ranked by how much it stops someone who presents with
PowerPoint from switching. This is the work list: pick from the top. Numbers are summarized in
@@ -13,6 +14,8 @@ tests (calibration in [target-app-parity.md](target-app-parity.md#calibration-ho
When a gap closes, delete its entry, update the parity doc it points to, and add a line to the
revision history.
Chart number-format reliability: explicit empty sections now hide the corresponding numeric labels, including all values with three semicolons. Blank whole-code General fallback remains. Synthetic formatter regressions cover section selection and quoted/escaped semicolons; broader chart-element gaps and readiness estimates below are unchanged.
## Ranked: the top 15
| # | Gap | Category | Beta | Hours | Doc |
@@ -358,6 +361,7 @@ Detail in [localization-parity.md](localization-parity.md).
| Date | Change | Summary |
|---|---|---|
| 2026-10-22 | minor | Animation Pane ▸ Play From starts the preview at the selected effect; gap 10 keeps the effect gallery (7–13 h) |
| 2026-10-20 | trivial | Explicit empty chart number-format sections hide their values; blank whole-code General fallback is retained. Synthetic formatter regressions; chart-element scores and readiness estimates unchanged |
| 2026-10-18 | minor | Native chart payloads use referenced ZIP members and share media byte/item limits; old inline sidecars remain readable. Synthetic tests cover multi-megabyte layout, all shape owners, shared budgets, missing/corrupt members and invalid references. Scores and milestone scope unchanged |
| 2026-10-15 | trivial | Native saves retain chart package parts and relationships, including charts in groups; edited chart data still does not export a stale source workbook. Chart editing gaps and scores remain unchanged |
| 2026-10-15 | trivial | PPTX trigger sequences keep later On Click steps instead of converting them to After Previous; mixed starts, independent buttons and paragraph builds have synthetic round-trip regressions |