diff --git a/crates/quarto-markdown-pandoc/src/pandoc/treesitter_utils/postprocess.rs b/crates/quarto-markdown-pandoc/src/pandoc/treesitter_utils/postprocess.rs index 632be54..df63a5b 100644 --- a/crates/quarto-markdown-pandoc/src/pandoc/treesitter_utils/postprocess.rs +++ b/crates/quarto-markdown-pandoc/src/pandoc/treesitter_utils/postprocess.rs @@ -412,6 +412,64 @@ pub fn postprocess(doc: Pandoc) -> Result> { if let Some(mut cite) = pending_cite.take() { // Add span content to the citation's suffix cite.citations[0].suffix = span.content.clone(); + + // Update the content field to include the rendered suffix with brackets + // Pandoc breaks up the bracketed suffix text by spaces, with the opening + // bracket attached to the first word and closing bracket to the last word + // e.g., "@knuth [p. 33]" becomes: Str("@knuth"), Space, Str("[p."), Space, Str("33]") + cite.content.push(Inline::Space(Space { + source_info: SourceInfo::with_range(empty_range()), + })); + + // The span content may have been merged into a single string, so we need to + // intelligently break it up to match Pandoc's behavior + let mut bracketed_content: Vec = vec![]; + for inline in &span.content { + if let Inline::Str(s) = inline { + // Split the string by spaces and create Str/Space inlines + let words: Vec<&str> = s.text.split(' ').collect(); + for (i, word) in words.iter().enumerate() { + if i > 0 { + bracketed_content.push(Inline::Space( + Space { + source_info: SourceInfo::with_range( + empty_range(), + ), + }, + )); + } + if !word.is_empty() { + bracketed_content.push(Inline::Str(Str { + text: word.to_string(), + source_info: s.source_info.clone(), + })); + } + } + } else { + bracketed_content.push(inline.clone()); + } + } + + // Now add brackets to the first and last Str elements + if !bracketed_content.is_empty() { + // Prepend "[" to the first Str element + if let Some(Inline::Str(first_str)) = + bracketed_content.first_mut() + { + first_str.text = format!("[{}", first_str.text); + } + // Append "]" to the last Str element (search from the end) + for i in (0..bracketed_content.len()).rev() { + if let Inline::Str(last_str) = + &mut bracketed_content[i] + { + last_str.text = format!("{}]", last_str.text); + break; + } + } + } + + cite.content.extend(bracketed_content); result.push(Inline::Cite(cite)); } state = 0; diff --git a/crates/quarto-markdown-pandoc/src/writers/qmd.rs b/crates/quarto-markdown-pandoc/src/writers/qmd.rs index 17b2835..d1b4076 100644 --- a/crates/quarto-markdown-pandoc/src/writers/qmd.rs +++ b/crates/quarto-markdown-pandoc/src/writers/qmd.rs @@ -974,6 +974,16 @@ fn write_cite(cite: &crate::pandoc::Cite, buf: &mut dyn std::io::Write) -> std:: write!(buf, "; ")?; } write!(buf, "@{}", citation.id)?; + + // Write suffix if it exists + // For AuthorInText mode, suffix appears as: @citation [suffix] + if !citation.suffix.is_empty() { + write!(buf, " [")?; + for inline in &citation.suffix { + write_inline(inline, buf)?; + } + write!(buf, "]")?; + } } } diff --git a/crates/quarto-markdown-pandoc/tests/roundtrip_tests/qmd-json-qmd/cite_with_suffix.qmd b/crates/quarto-markdown-pandoc/tests/roundtrip_tests/qmd-json-qmd/cite_with_suffix.qmd new file mode 100644 index 0000000..40148b2 --- /dev/null +++ b/crates/quarto-markdown-pandoc/tests/roundtrip_tests/qmd-json-qmd/cite_with_suffix.qmd @@ -0,0 +1 @@ +@knuth [p. 33] diff --git a/crates/quarto-markdown-pandoc/tests/snapshots/native/006.qmd.snapshot b/crates/quarto-markdown-pandoc/tests/snapshots/native/006.qmd.snapshot index 419c06a..e232548 100644 --- a/crates/quarto-markdown-pandoc/tests/snapshots/native/006.qmd.snapshot +++ b/crates/quarto-markdown-pandoc/tests/snapshots/native/006.qmd.snapshot @@ -1 +1 @@ -[ Para [Cite [Citation { citationId = "smith04", citationPrefix = [], citationSuffix = [Str "p. 33"], citationMode = AuthorInText, citationNoteNum = 1, citationHash = 0 }] [Str "@smith04"]] ] \ No newline at end of file +[ Para [Cite [Citation { citationId = "smith04", citationPrefix = [], citationSuffix = [Str "p. 33"], citationMode = AuthorInText, citationNoteNum = 1, citationHash = 0 }] [Str "@smith04", Space, Str "[p. 33]"]] ] \ No newline at end of file