Skip to content

Commit df453ef

Browse files
authored
Fix cite processing in reader and qmd writer (#42)
* improve cite processing on the front-end (#40) * fix cite in qmd writer (#40)
1 parent 178779c commit df453ef

File tree

4 files changed

+70
-1
lines changed

4 files changed

+70
-1
lines changed

crates/quarto-markdown-pandoc/src/pandoc/treesitter_utils/postprocess.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,64 @@ pub fn postprocess(doc: Pandoc) -> Result<Pandoc, Vec<String>> {
412412
if let Some(mut cite) = pending_cite.take() {
413413
// Add span content to the citation's suffix
414414
cite.citations[0].suffix = span.content.clone();
415+
416+
// Update the content field to include the rendered suffix with brackets
417+
// Pandoc breaks up the bracketed suffix text by spaces, with the opening
418+
// bracket attached to the first word and closing bracket to the last word
419+
// e.g., "@knuth [p. 33]" becomes: Str("@knuth"), Space, Str("[p."), Space, Str("33]")
420+
cite.content.push(Inline::Space(Space {
421+
source_info: SourceInfo::with_range(empty_range()),
422+
}));
423+
424+
// The span content may have been merged into a single string, so we need to
425+
// intelligently break it up to match Pandoc's behavior
426+
let mut bracketed_content: Vec<Inline> = vec![];
427+
for inline in &span.content {
428+
if let Inline::Str(s) = inline {
429+
// Split the string by spaces and create Str/Space inlines
430+
let words: Vec<&str> = s.text.split(' ').collect();
431+
for (i, word) in words.iter().enumerate() {
432+
if i > 0 {
433+
bracketed_content.push(Inline::Space(
434+
Space {
435+
source_info: SourceInfo::with_range(
436+
empty_range(),
437+
),
438+
},
439+
));
440+
}
441+
if !word.is_empty() {
442+
bracketed_content.push(Inline::Str(Str {
443+
text: word.to_string(),
444+
source_info: s.source_info.clone(),
445+
}));
446+
}
447+
}
448+
} else {
449+
bracketed_content.push(inline.clone());
450+
}
451+
}
452+
453+
// Now add brackets to the first and last Str elements
454+
if !bracketed_content.is_empty() {
455+
// Prepend "[" to the first Str element
456+
if let Some(Inline::Str(first_str)) =
457+
bracketed_content.first_mut()
458+
{
459+
first_str.text = format!("[{}", first_str.text);
460+
}
461+
// Append "]" to the last Str element (search from the end)
462+
for i in (0..bracketed_content.len()).rev() {
463+
if let Inline::Str(last_str) =
464+
&mut bracketed_content[i]
465+
{
466+
last_str.text = format!("{}]", last_str.text);
467+
break;
468+
}
469+
}
470+
}
471+
472+
cite.content.extend(bracketed_content);
415473
result.push(Inline::Cite(cite));
416474
}
417475
state = 0;

crates/quarto-markdown-pandoc/src/writers/qmd.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,16 @@ fn write_cite(cite: &crate::pandoc::Cite, buf: &mut dyn std::io::Write) -> std::
974974
write!(buf, "; ")?;
975975
}
976976
write!(buf, "@{}", citation.id)?;
977+
978+
// Write suffix if it exists
979+
// For AuthorInText mode, suffix appears as: @citation [suffix]
980+
if !citation.suffix.is_empty() {
981+
write!(buf, " [")?;
982+
for inline in &citation.suffix {
983+
write_inline(inline, buf)?;
984+
}
985+
write!(buf, "]")?;
986+
}
977987
}
978988
}
979989

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@knuth [p. 33]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[ Para [Cite [Citation { citationId = "smith04", citationPrefix = [], citationSuffix = [Str "p. 33"], citationMode = AuthorInText, citationNoteNum = 1, citationHash = 0 }] [Str "@smith04"]] ]
1+
[ Para [Cite [Citation { citationId = "smith04", citationPrefix = [], citationSuffix = [Str "p. 33"], citationMode = AuthorInText, citationNoteNum = 1, citationHash = 0 }] [Str "@smith04", Space, Str "[p. 33]"]] ]

0 commit comments

Comments
 (0)