Merge branch 'pr/522' into batch1
This commit is contained in:
commit
d5613411ca
|
|
@ -142,6 +142,7 @@ Newest first.
|
|||
- **2026-10-12** · Hyphenation Zone applies to the Single-line Composer only, as in InDesign. With the default Paragraph Composer, ragged text hyphenates where InDesign does (aper-natem), giving the same line breaks. No readiness percentage change.
|
||||
- **2026-10-12** · The Tools panel's Fill/Stroke keys work: D (default fill and stroke), X (fill or stroke in front), Shift+X (swap per object, tints included) and / (Apply None), as `color.*` commands; swap and default are one undo step (`object.swapFillStroke`, `object.defaultFillStroke`); the Color panel follows the proxy's fill/stroke choice. No readiness percentage change.
|
||||
- **2026-10-11** · Corner Options keep curved sides curved and round every corner point, including where an arc meets a line (a Pathfinder quarter circle with rounded corners stayed a triangle). No readiness percentage change.
|
||||
- **2026-10-11** · `story.replaceRange`, `story.setText`, notes, footnotes, endnotes, type on a path and table cells read `\r` and `\r\n` as paragraph returns, as `frame.create` and `text.insert` already did. No readiness percentage change.
|
||||
- **2026-10-12** · Words in capitals hyphenate like capitalized words (FERRUM COM-MODI), as in InDesign; Hyphenate Capitalized Words off keeps them whole. No readiness percentage change.
|
||||
- **2026-10-11** · `transform.move {copy}`, Edit › Duplicate and Step and Repeat return the copies' ids, so a script can go on with them. No readiness percentage change.
|
||||
- **2026-10-11** · `object.fill` and `object.stroke` refuse a swatch name the document doesn't have (it painted nothing) and suggest the name meant (`Paper` → `[Paper]`). No readiness percentage change.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
if ts.cell.is_some() {
|
||||
return Err(bad("note.new", "notes go in story text"));
|
||||
}
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
let author = str_param(p, "author").unwrap_or("").to_string();
|
||||
let at = ts.anchor.max(ts.focus);
|
||||
s.edit(|d, sel| {
|
||||
|
|
@ -36,7 +36,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
}),
|
||||
cmd!("note.edit", "Edit Note", [], None, "{story, id, text?, author?}", has_doc, |s, p| {
|
||||
let (sid, id) = target(p)?;
|
||||
let (text, author) = (str_param(p, "text").map(str::to_string), str_param(p, "author").map(str::to_string));
|
||||
let (text, author) = (str_param(p, "text").map(|_| super::text_param(p, "text")), str_param(p, "author").map(str::to_string));
|
||||
s.edit(|d, _| {
|
||||
let st = d.story_mut(sid).ok_or_else(|| bad("note.edit", "no such story"))?;
|
||||
let n = st.editorial.iter_mut().find(|n| n.id == id).ok_or_else(|| bad("note.edit", format!("no note {id}")))?;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
use designcraft_doc::{ParaFormat, SpreadRef, StoryId};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::{CommandSpec, bad, cmd, has_doc, has_text, ok, str_param};
|
||||
use super::{CommandSpec, bad, cmd, has_doc, has_text, ok};
|
||||
use crate::{Result, Session};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
|
@ -20,7 +20,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
),
|
||||
cmd!("endnote.edit", "Edit Endnote", [], None, "{story, id, text}", has_doc, |s, p| {
|
||||
let (sid, id) = target(p)?;
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
s.edit(|d, _| {
|
||||
let style = d.endnote_options.para_style.clone();
|
||||
let st = d.story_mut(sid).ok_or_else(|| bad("endnote.edit", "no such story"))?;
|
||||
|
|
@ -103,7 +103,7 @@ fn insert(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
if st.doc.endnote_story == Some(ts.story) {
|
||||
return Err(bad(ID, "the endnote frame lists the endnotes"));
|
||||
}
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
let at = ts.anchor.max(ts.focus);
|
||||
s.edit(|d, sel| {
|
||||
// The endnote frame: a text frame in the margins of a new last page.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use designcraft_doc::{CellAddr, FootnoteOptions, ParaFormat, StoryId, TextSel};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use super::{CommandSpec, bad, cmd, has_doc, str_param};
|
||||
use super::{CommandSpec, bad, cmd, has_doc};
|
||||
use crate::{Result, Session};
|
||||
|
||||
pub fn specs() -> Vec<CommandSpec> {
|
||||
|
|
@ -58,7 +58,7 @@ fn in_note(s: &Session) -> std::result::Result<(), String> {
|
|||
}
|
||||
|
||||
fn insert(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
s.edit(|d, sel| {
|
||||
let t = sel.text.ok_or_else(|| bad("footnote.insert", "no insertion point"))?;
|
||||
let para = ParaFormat { style: d.footnote_options.para_style.clone(), ..Default::default() };
|
||||
|
|
@ -130,7 +130,7 @@ fn list(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
fn set_text(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let sid = story_id(p, "footnote.setText")?;
|
||||
let id = note_id(p, "footnote.setText")?;
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
s.edit(|d, _| {
|
||||
let st = d.story_mut(sid).ok_or(designcraft_doc::DocError::NoStory(sid))?;
|
||||
let n = st.note_mut(id).ok_or_else(|| bad("footnote.setText", format!("no footnote {id}")))?;
|
||||
|
|
|
|||
|
|
@ -3022,6 +3022,18 @@ mod line_end_tests {
|
|||
s.execute("text.insert", &json!({"text": "\rFour", "raw": true})).unwrap();
|
||||
assert_eq!(story(&s).text, "One\nTwo\nThree\nFour");
|
||||
assert_eq!(story(&s).paras.len(), 4);
|
||||
// Editing a range or the whole story (scripts written for InDesign end paragraphs with \r).
|
||||
s.execute("story.replaceRange", &json!({"story": sid.0, "start": 0, "end": 3, "text": "Zero\rOne"})).unwrap();
|
||||
assert_eq!((story(&s).text.as_str(), story(&s).paras.len()), ("Zero\nOne\nTwo\nThree\nFour", 5));
|
||||
s.execute("story.setText", &json!({"story": sid.0, "text": "A\r\nB\rC"})).unwrap();
|
||||
assert_eq!((story(&s).text.as_str(), story(&s).paras.len()), ("A\nB\nC", 3));
|
||||
// Notes, made and edited.
|
||||
s.execute("text.select", &json!({"story": sid.0, "anchor": 1})).unwrap();
|
||||
let n = s.execute("note.new", &json!({"text": "One\rTwo"})).unwrap();
|
||||
let note = |s: &mut Session| s.execute("note.list", &json!({})).unwrap()[0]["text"].clone();
|
||||
assert_eq!(note(&mut s), "One\nTwo");
|
||||
s.execute("note.edit", &json!({"story": n["story"], "id": n["id"], "text": "Three\r\nFour"})).unwrap();
|
||||
assert_eq!(note(&mut s), "Three\nFour");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ fn align_param(p: &Value) -> Result<Option<PathAlign>> {
|
|||
|
||||
fn on_path(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let id = super::id_param(p, "id").ok_or_else(|| bad("type.onPath", "missing id"))?;
|
||||
let text = super::str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
let mut pt = PathType {
|
||||
start: p.get("start").and_then(Value::as_f64).unwrap_or(0.0).max(0.0),
|
||||
flip: p.get("flip").and_then(Value::as_bool).unwrap_or(false),
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@ fn set_cell(s: &mut Session, p: &Value) -> Result<Value> {
|
|||
Some(o) => return Err(bad("table.setCell", format!("unknown vj `{o}`"))),
|
||||
None => None,
|
||||
};
|
||||
let text = str_param(p, "text").map(str::to_string);
|
||||
let text = str_param(p, "text").map(|_| super::text_param(p, "text"));
|
||||
let stroke = p.get("stroke").cloned();
|
||||
edit_table(s, &g, "table.setCell", |t| {
|
||||
let owners = t.owners();
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
),
|
||||
cmd!("story.setText", "Set Story Text", [], None, "{story, text} — replace a story's whole text", has_doc, |s, p| {
|
||||
let sid = StoryId(p.get("story").and_then(Value::as_u64).ok_or_else(|| bad("story.setText", "missing story"))?);
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
s.edit(|d, sel| {
|
||||
d.set_story_text(sid, &text)?;
|
||||
if let Some(t) = sel.text.as_mut().filter(|t| t.story == sid) {
|
||||
|
|
@ -106,7 +106,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
|||
let sid = StoryId(p.get("story").and_then(Value::as_u64).ok_or_else(|| bad("story.replaceRange", "missing story"))?);
|
||||
let a = p.get("start").and_then(Value::as_u64).unwrap_or(0) as usize;
|
||||
let b = p.get("end").and_then(Value::as_u64).map(|v| v as usize).unwrap_or(a);
|
||||
let text = str_param(p, "text").unwrap_or("").to_string();
|
||||
let text = super::text_param(p, "text");
|
||||
s.edit(|d, sel| {
|
||||
let st = d.story_mut(sid).ok_or(designcraft_doc::DocError::NoStory(sid))?;
|
||||
let (a, b) = (a.min(st.len()), b.min(st.len()).max(a.min(st.len())));
|
||||
|
|
|
|||
Loading…
Reference in New Issue