| ... | @@ -671,6 +671,7 @@ impl Lowering<'_> { | ... | @@ -671,6 +671,7 @@ impl Lowering<'_> { |
| 671 | if stored.text.text() != text.text.text() { | 671 | if stored.text.text() != text.text.text() { |
| 672 | return Err(invalid("Text edits did not converge on the model")); | 672 | return Err(invalid("Text edits did not converge on the model")); |
| 673 | } | 673 | } |
| | 674 | let fresh = self.alias.contains_key(&text.id); |
| 674 | let mut boundaries = BTreeSet::new(); | 675 | let mut boundaries = BTreeSet::new(); |
| 675 | for paragraph in [&stored.text, &text.text] { | 676 | for paragraph in [&stored.text, &text.text] { |
| 676 | for span in paragraph.spans() { | 677 | for span in paragraph.spans() { |
| ... | @@ -689,6 +690,7 @@ impl Lowering<'_> { | ... | @@ -689,6 +690,7 @@ impl Lowering<'_> { |
| 689 | let attributes = attributes( | 690 | let attributes = attributes( |
| 690 | format_in(&stored.text, start)?, | 691 | format_in(&stored.text, start)?, |
| 691 | format_in(&text.text, start)?, | 692 | format_in(&text.text, start)?, |
| | 693 | fresh, |
| 692 | )?; | 694 | )?; |
| 693 | match &mut pending { | 695 | match &mut pending { |
| 694 | Some((range, previous)) if *previous == attributes && range.end == start => { | 696 | Some((range, previous)) if *previous == attributes && range.end == start => { |
| ... | @@ -704,8 +706,11 @@ impl Lowering<'_> { | ... | @@ -704,8 +706,11 @@ impl Lowering<'_> { |
| 704 | } | 706 | } |
| 705 | edits.extend(pending); | 707 | edits.extend(pending); |
| 706 | if text.text.text().is_empty() { | 708 | if text.text.text().is_empty() { |
| 707 | let attributes = | 709 | let attributes = attributes( |
| 708 | attributes(format_in(&stored.text, 0)?, format_in(&text.text, 0)?)?; | 710 | format_in(&stored.text, 0)?, |
| | 711 | format_in(&text.text, 0)?, |
| | 712 | fresh, |
| | 713 | )?; |
| 709 | if !attributes.is_empty() { | 714 | if !attributes.is_empty() { |
| 710 | edits.push((0..0, attributes)); | 715 | edits.push((0..0, attributes)); |
| 711 | } | 716 | } |
| ... | @@ -900,17 +905,19 @@ fn text_edit(before: &str, after: &str) -> Result<(Range<u32>, String), Error> { | ... | @@ -900,17 +905,19 @@ fn text_edit(before: &str, after: &str) -> Result<(Range<u32>, String), Error> { |
| 900 | } | 905 | } |
| 901 | | 906 | |
| 902 | /// Explicit attributes turning `current` into `target`; unsupported differences are errors. | 907 | /// Explicit attributes turning `current` into `target`; unsupported differences are errors. |
| | 908 | /// A `fresh` text object was inserted by this edit, so an unspecified target value keeps |
| | 909 | /// the insertion's default instead of demanding an inherited value the image cannot restore. |
| 903 | /// Language tags are retained as stored because the model has no way to author them. | 910 | /// Language tags are retained as stored because the model has no way to author them. |
| 904 | fn attributes(current: &Format, target: &Format) -> Result<Vec<TextAttribute>, Error> { | 911 | fn attributes(current: &Format, target: &Format, fresh: bool) -> Result<Vec<TextAttribute>, Error> { |
| 905 | let mut out = Vec::new(); | 912 | let mut out = Vec::new(); |
| | 913 | let inherited = || invalid("Inherited character formatting cannot be restored"); |
| 906 | macro_rules! boolean { | 914 | macro_rules! boolean { |
| 907 | ($field:ident, $variant:ident) => { | 915 | ($field:ident, $variant:ident) => { |
| 908 | if current.$field != target.$field { | 916 | if current.$field != target.$field { |
| 909 | match target.$field { | 917 | match target.$field { |
| 910 | Some(value) => out.push(TextAttribute::$variant(value)), | 918 | Some(value) => out.push(TextAttribute::$variant(value)), |
| 911 | None => { | 919 | None if fresh => {} |
| 912 | return Err(invalid("Inherited character formatting cannot be restored")); | 920 | None => return Err(inherited()), |
| 913 | } | | |
| 914 | } | 921 | } |
| 915 | } | 922 | } |
| 916 | }; | 923 | }; |
| ... | @@ -924,13 +931,15 @@ fn attributes(current: &Format, target: &Format) -> Result<Vec<TextAttribute>, E | ... | @@ -924,13 +931,15 @@ fn attributes(current: &Format, target: &Format) -> Result<Vec<TextAttribute>, E |
| 924 | if current.font != target.font { | 931 | if current.font != target.font { |
| 925 | match &target.font { | 932 | match &target.font { |
| 926 | Some(font) => out.push(TextAttribute::Font(font.clone())), | 933 | Some(font) => out.push(TextAttribute::Font(font.clone())), |
| 927 | None => return Err(invalid("Inherited character formatting cannot be restored")), | 934 | None if fresh => {} |
| | 935 | None => return Err(inherited()), |
| 928 | } | 936 | } |
| 929 | } | 937 | } |
| 930 | if current.font_size != target.font_size { | 938 | if current.font_size != target.font_size { |
| 931 | match target.font_size { | 939 | match target.font_size { |
| 932 | Some(size) => out.push(TextAttribute::FontSize(size)), | 940 | Some(size) => out.push(TextAttribute::FontSize(size)), |
| 933 | None => return Err(invalid("Inherited character formatting cannot be restored")), | 941 | None if fresh => {} |
| | 942 | None => return Err(inherited()), |
| 934 | } | 943 | } |
| 935 | } | 944 | } |
| 936 | let color = | 945 | let color = |
| ... | @@ -938,13 +947,15 @@ fn attributes(current: &Format, target: &Format) -> Result<Vec<TextAttribute>, E | ... | @@ -938,13 +947,15 @@ fn attributes(current: &Format, target: &Format) -> Result<Vec<TextAttribute>, E |
| 938 | if current.color != target.color { | 947 | if current.color != target.color { |
| 939 | match target.color { | 948 | match target.color { |
| 940 | Some(value) => out.push(TextAttribute::Color(color(value))), | 949 | Some(value) => out.push(TextAttribute::Color(color(value))), |
| 941 | None => return Err(invalid("Inherited character formatting cannot be restored")), | 950 | None if fresh => {} |
| | 951 | None => return Err(inherited()), |
| 942 | } | 952 | } |
| 943 | } | 953 | } |
| 944 | if current.highlight != target.highlight { | 954 | if current.highlight != target.highlight { |
| 945 | match target.highlight { | 955 | match target.highlight { |
| 946 | Some(value) => out.push(TextAttribute::Highlight(color(value))), | 956 | Some(value) => out.push(TextAttribute::Highlight(color(value))), |
| 947 | None => return Err(invalid("Inherited character formatting cannot be restored")), | 957 | None if fresh => {} |
| | 958 | None => return Err(inherited()), |
| 948 | } | 959 | } |
| 949 | } | 960 | } |
| 950 | // An absent value and its stored default are the same formatting. | 961 | // An absent value and its stored default are the same formatting. |