mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-24 10:16:59 -06:00
Text: footnotes insert into a story whose references lack footnotes
This commit is contained in:
@@ -166,15 +166,18 @@ impl Story {
|
||||
self.text.match_indices(FOOTNOTE_REF).nth(k).map(|(i, _)| i)
|
||||
}
|
||||
|
||||
/// Insert a footnote reference at `pos` with the given footnote text. Returns the footnote id.
|
||||
pub fn insert_note(&mut self, pos: usize, text: &str, para: ParaFormat) -> u64 {
|
||||
/// Insert a footnote reference at `pos` with the given footnote text. Returns the footnote
|
||||
/// id, or `None` if the story has no footnote for the new reference.
|
||||
pub fn insert_note(&mut self, pos: usize, text: &str, para: ParaFormat) -> Option<u64> {
|
||||
let pos = crate::story::floor_char_boundary(&self.text, pos.min(self.len()));
|
||||
let fmt = self.char_format_at(pos).clone();
|
||||
self.insert_with(pos, &FOOTNOTE_REF.to_string(), fmt);
|
||||
// A file may hold fewer footnotes than references; give every reference one.
|
||||
self.fix_notes();
|
||||
let k = self.notes_before(pos);
|
||||
let note = Arc::make_mut(&mut self.notes[k]);
|
||||
let note = Arc::make_mut(self.notes.get_mut(k)?);
|
||||
note.text = Story::with_text(StoryId(0), text, para);
|
||||
note.id
|
||||
Some(note.id)
|
||||
}
|
||||
|
||||
pub(crate) fn next_note_id(&self) -> u64 {
|
||||
@@ -283,8 +286,8 @@ mod tests {
|
||||
#[test]
|
||||
fn references_own_notes_in_order() {
|
||||
let mut s = st("alpha beta gamma");
|
||||
let b = s.insert_note(10, "second", ParaFormat::default());
|
||||
let a = s.insert_note(5, "first", ParaFormat::default());
|
||||
let b = s.insert_note(10, "second", ParaFormat::default()).unwrap();
|
||||
let a = s.insert_note(5, "first", ParaFormat::default()).unwrap();
|
||||
s.check().unwrap();
|
||||
assert_eq!(s.notes.len(), 2);
|
||||
assert_eq!(s.notes[0].id, a);
|
||||
|
||||
@@ -142,18 +142,21 @@ mod tests {
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
let r = s.execute("frame.create", &json!({"rect": [72, 72, 400, 300], "content": "text", "text": "Draft copy."})).unwrap();
|
||||
let sid = designcraft_doc::StoryId(r["story"].as_u64().unwrap());
|
||||
// A damaged file: a note anchor and an endnote reference without payloads.
|
||||
// A damaged file: a note anchor, an endnote and a footnote reference without payloads.
|
||||
let st = std::sync::Arc::make_mut(&mut s.doc_mut().unwrap().doc).story_mut(sid).unwrap();
|
||||
st.insert(0, &format!("{}{}", designcraft_doc::NOTE_MARK, designcraft_doc::ENDNOTE_REF));
|
||||
st.insert(0, &format!("{}{}{}", designcraft_doc::NOTE_MARK, designcraft_doc::ENDNOTE_REF, designcraft_doc::FOOTNOTE_REF));
|
||||
st.editorial.clear();
|
||||
st.endnotes.clear();
|
||||
st.notes.clear();
|
||||
let end = st.len();
|
||||
s.execute("text.select", &json!({"story": r["story"], "anchor": end, "focus": end})).unwrap();
|
||||
s.execute("note.new", &json!({"text": "check this"})).unwrap();
|
||||
s.execute("endnote.insert", &json!({"text": "An endnote."})).unwrap();
|
||||
s.execute("footnote.insert", &json!({"text": "A footnote."})).unwrap();
|
||||
let st = &s.doc().unwrap().doc.stories[&sid];
|
||||
st.check().unwrap();
|
||||
assert_eq!(st.editorial[1].text, "check this");
|
||||
assert_eq!(st.endnotes[1].text.text, "An endnote.");
|
||||
assert_eq!(st.notes[1].text.text, "A footnote.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ fn insert(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let r = t.range();
|
||||
let r = r.start.min(st.len())..r.end.min(st.len());
|
||||
st.delete(r.clone());
|
||||
let id = st.insert_note(r.start, &text, para);
|
||||
let id = st.insert_note(r.start, &text, para).ok_or_else(|| bad("footnote.insert", "the story's footnotes don't match their references"))?;
|
||||
sel.text = Some(TextSel { story: t.story, anchor: text.len(), focus: text.len(), frame: t.frame, cell: Some(CellAddr::footnote(id)) });
|
||||
Ok(json!({"story": t.story.0, "id": id}))
|
||||
})
|
||||
|
||||
@@ -305,9 +305,13 @@ impl Ctx {
|
||||
self.blocks(¬e, &mut ns, false);
|
||||
// Word puts the reference mark in the note text: we generate the number.
|
||||
let len = st.len();
|
||||
let id = st.insert_note(len, "", ParaFormat::default());
|
||||
if let Some(n) = st.note_mut(id) {
|
||||
n.text = ns;
|
||||
match st.insert_note(len, "", ParaFormat::default()) {
|
||||
Some(id) => {
|
||||
if let Some(n) = st.note_mut(id) {
|
||||
n.text = ns;
|
||||
}
|
||||
}
|
||||
None => self.warnings.push("A footnote in the Word file could not be imported.".into()),
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user