mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-29 21:07:24 -06:00
Inserting a second shape removed the first: after an insert the new shape stays selected, and `insert.shape` replaced the selection, so each shape replaced the one before. Word draws a new shape beside whatever is selected and never deletes it (checked by hand in Word for Windows: a second shape is drawn over the first, which stays). The new shape now goes after the selection, which is left alone, and becomes the selection. Selected text stays too. A picture still replaces a selected picture, which is what Word does as well (checked in Word for Windows), so `insert.picture` is unchanged. Tests: three shapes inserted in a row are all kept, which fails with the old code (1 of 3 kept); a shape inserted over selected text keeps the text and is selected itself; a picture inserted over a selected picture replaces it. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
Brandon Thomas
parent
7333a302f5
commit
1b45615940
@@ -348,8 +348,11 @@ fn shape(s: &mut Session, v: &Value) -> CmdResult {
|
||||
if super::canvas::add_member(s, obj.clone())?.is_some() {
|
||||
return sel_result(s);
|
||||
}
|
||||
// Word draws a new shape beside what is selected and never deletes it: the shape just
|
||||
// inserted (which is selected) stays, and so does selected text (#2019). It goes after the
|
||||
// selection and becomes the selection. (A picture does replace the selection, as in Word.)
|
||||
let props = s.typing_props();
|
||||
let at = delete_selection(s)?;
|
||||
let (_, at) = s.sel.ordered();
|
||||
let end = s.doc.insert_object(&at, obj, &props)?;
|
||||
s.sel = Selection { anchor: at, focus: end };
|
||||
sel_result(s)
|
||||
|
||||
@@ -1594,6 +1594,41 @@ mod tests {
|
||||
assert_eq!(s.run("arrange.selectionPane", &json!({})).unwrap().as_array().map(Vec::len), Some(2));
|
||||
}
|
||||
|
||||
/// #2019: Insert › Shapes adds each new shape beside the selected one, as Word draws it, so
|
||||
/// shapes inserted in a row are all kept (the second used to replace the first, which stays
|
||||
/// selected after its insert). Selected text stays too, and the new shape is selected.
|
||||
#[test]
|
||||
fn shapes_inserted_in_a_row_are_all_kept_and_keep_selected_text() {
|
||||
let objects = |s: &mut Session| s.run("arrange.selectionPane", &json!({})).unwrap().as_array().map(Vec::len);
|
||||
let mut s = Session::new(wordcraft_doc::Document::new());
|
||||
for kind in ["rectangle", "ellipse", "star"] {
|
||||
s.run("insert.shape", &json!({"kind": kind})).unwrap();
|
||||
}
|
||||
assert_eq!(objects(&mut s), Some(3));
|
||||
|
||||
let mut s = Session::new(wordcraft_doc::Document::from_text("Kiln room"));
|
||||
s.run("select.text", &json!({"text": "Kiln"})).unwrap();
|
||||
s.run("insert.shape", &json!({"kind": "rectangle"})).unwrap();
|
||||
let text = s.doc.plain_text(StoryRef::Body);
|
||||
assert!(text.starts_with("Kiln") && text.ends_with(" room"), "{text:?}");
|
||||
assert_eq!(objects(&mut s), Some(1));
|
||||
let (a, b) = s.sel.ordered();
|
||||
let obj = wordcraft_doc::para::OBJ.len_utf8();
|
||||
assert_eq!((a.off, b.off), (4, 4 + obj), "the new shape, after the text, is selected");
|
||||
}
|
||||
|
||||
/// Insert › Pictures does replace a selected picture, as Word does (checked in Word for
|
||||
/// Windows while fixing #2019): only shapes are added beside the selection.
|
||||
#[test]
|
||||
fn an_inserted_picture_replaces_a_selected_picture() {
|
||||
let data = super::super::insert::base64_encode(&png(20, 10));
|
||||
let mut s = Session::new(wordcraft_doc::Document::new());
|
||||
s.run("insert.picture", &json!({"data": data})).unwrap();
|
||||
s.sel = crate::Selection { anchor: Pos::body(0, 0), focus: Pos::body(0, wordcraft_doc::para::OBJ.len_utf8()) };
|
||||
s.run("insert.picture", &json!({"data": data})).unwrap();
|
||||
assert_eq!(s.run("arrange.selectionPane", &json!({})).unwrap().as_array().map(Vec::len), Some(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn picture_pipeline() {
|
||||
let mut s = Session::new(wordcraft_doc::Document::new());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# WordCraft parity with Microsoft Word
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-16 · **Change:** trivial (East Asian typography: `w:eastAsianLayout` kept on save, not laid out; previously trivial: Ink to Shape recognises arrows; previously trivial: Windows Magnifier follows the caret onto a new line, #1119; previously trivial: table border drags with Ctrl and Alt, from the left edge and of selected cells, #711; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: all 12 bibliography styles, #383; previously trivial: formatting revisions landed, #41; previously trivial: Draw Table and Eraser landed, #303; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; replaces the parity tables that lived in ROADMAP.md) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-16 · **Change:** trivial (shapes inserted in a row are all kept, #2019; previously trivial: East Asian typography: `w:eastAsianLayout` kept on save, not laid out; previously trivial: Ink to Shape recognises arrows; previously trivial: Windows Magnifier follows the caret onto a new line, #1119; previously trivial: table border drags with Ctrl and Alt, from the left edge and of selected cells, #711; previously trivial: table column and row markers on the rulers, #700; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: all 12 bibliography styles, #383; previously trivial: formatting revisions landed, #41; previously trivial: Draw Table and Eraser landed, #303; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; replaces the parity tables that lived in ROADMAP.md) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
|
||||
The authoritative assessment of how close WordCraft is to Microsoft Word. [`ROADMAP.md`](../ROADMAP.md)
|
||||
summarizes it; [`gaps.md`](gaps.md) itemizes every shortfall; the deep checklists are
|
||||
@@ -251,9 +251,11 @@ can be used without committing Word output.
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-15 | trivial | Pictures, shapes, text boxes: Insert › Shapes adds the new shape beside the selection, as Word draws it, so a second shape no longer replaces the first (still selected after its insert) and selected text stays; a picture still replaces a selected picture, as in Word (#2019) |
|
||||
| 2026-10-16 | trivial | East Asian typography row: `w:eastAsianLayout` kept on save, not laid out; no percentage change |
|
||||
| 2026-10-15 | trivial | Equations: a script or limit after `_` or `^` is the whole run of letters and digits (`V_dd`, `x^ab`), as in Word for Mac 16.113.4, and Linear format writes it bare (#1609) |
|
||||
| 2026-10-15 | trivial | Tables: Cell Margins (#1960) opens initialized from table defaults and applies edits only after confirmation; per-cell margins remain intact |
|
||||
| 2026-10-15 | trivial | Pictures, shapes, text boxes: Insert › Shapes adds the new shape beside the selection, as Word draws it, so a second shape no longer replaces the first (still selected after its insert) and selected text stays; a picture still replaces a selected picture, as in Word (#2019) |
|
||||
| 2026-10-12 | minor | Czech proofing review: short-word splits rank after deletion, NOSUGGEST excludes suggestions while accepting typed forms, affix comments apply only to headers, ratios keep spaces and repeated-word messages use Czech quotes; synthetic engine end-to-end and latency checks |
|
||||
| 2026-10-12 | minor | Czech spelling from the installed Hunspell dictionary, runtime-table suggestions and generic checks; Czech interface writes cs-CZ documents; no Czech hyphenation patterns bundled; estimates unchanged |
|
||||
| 2026-10-13 | trivial | Windows Magnifier follows the caret onto a new line (#1119): Accessibility row updated; no percentage change |
|
||||
|
||||
Reference in New Issue
Block a user