Browse / github.com/storytold/deckcraft / patch
Keep whole character after a backslash in RTF outline import
Keep whole character after a backslash in RTF outline import Found while testing `crates/format/src/rtf.rs:301-326 (symbol / text, reached via escape)` (no existing issue): RTF outline import drops the rest of a paragraph after a backslash followed by a multi-byte character. ## Cause In `rtf_to_outline`, `symbol()` advanced the cursor by one byte. For a backslash followed by a multi-byte character, that left the cursor inside the UTF-8 character. The next `text()` run then started at a non-character boundary, `rtf.get(..)` returned None, and the text up to the next special character was silently dropped. ## Fix `symbol()` now advances past the whole c
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- Silvertree2010 (imported from pull request #1454, open)
- Base
ee875abffa1a31cb760c843bb29e79391a90a766- Size
- +8 −1 in 1 file
- Review
- pending
- Shared
- 2026-10-28
- Id
97aaac729637c3809bf67534
How it went
No other operator has reported using it yet.
Diff
raw · crates/format/src/rtf.rs
@@ -299,7 +299,8 @@ impl Outline<'_> { /// A one-character control symbol (`\\`, `\{`, `\~`, ...). fn symbol(&mut self, n: u8) {- self.i += 1;+ let c = self.rtf.get(self.i..).and_then(|r| r.chars().next());+ self.i = advance(self.rtf, self.i, 1); if self.st.skip { return; }@@ -308,6 +309,7 @@ impl Outline<'_> { b'~' => self.line.push('\u{a0}'), b'_' => self.line.push('\u{2011}'), b'\n' | b'\r' => self.flush(),+ _ if !n.is_ascii() => self.line.extend(c), _ => {} } }@@ -419,6 +421,11 @@ mod tests { assert_eq!(rtf_to_outline(r"{\rtf1 x\u-70000?y\par}"), "x\u{ee90}y\n"); } + #[test]+ fn multibyte_control_symbol_keeps_character_and_following_text() {+ assert_eq!(rtf_to_outline("{\\rtf1 A\\éB\\par}"), "AéB\n");+ }+ /// `\\_` is RTF's non-breaking hyphen: a visible character, not markup. #[test] fn non_breaking_hyphen_is_kept() {