From cf133dc42b00f5cc4d20106da66b3d85826cff58 Mon Sep 17 00:00:00 2001 From: subotac <73706465+subotac@users.noreply.github.com> Date: Thu, 30 Jul 2026 00:10:56 +0300 Subject: [PATCH] Fix Markdown docs with source-like syntax --- crates/core/src/source.rs | 25 ++++++++++++++++++++++--- crates/markdown/src/lib.rs | 2 +- crates/markdown/tests/codegen.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 crates/markdown/tests/codegen.rs diff --git a/crates/core/src/source.rs b/crates/core/src/source.rs index 3c40b0fc7..bf9382ae7 100644 --- a/crates/core/src/source.rs +++ b/crates/core/src/source.rs @@ -49,6 +49,16 @@ impl Source { } pub fn push_str(&mut self, src: &str) { + self.push_str_impl(src, true); + } + + /// Appends literal text with the current indentation without interpreting + /// braces or line comments as source syntax. + pub fn push_str_literal(&mut self, src: &str) { + self.push_str_impl(src, false); + } + + fn push_str_impl(&mut self, src: &str, interpret_syntax: bool) { let lines = src.lines().collect::>(); for (i, line) in lines.iter().enumerate() { if !self.continuing_line { @@ -61,11 +71,11 @@ impl Source { } let trimmed = line.trim(); - if trimmed.starts_with("//") { + if interpret_syntax && trimmed.starts_with("//") { self.in_line_comment = true; } - if !self.in_line_comment { + if interpret_syntax && !self.in_line_comment { if trimmed.starts_with('}') && self.s.ends_with(" ") { self.s.pop(); self.s.pop(); @@ -76,7 +86,7 @@ impl Source { } else { line.trim_start() }); - if !self.in_line_comment { + if interpret_syntax && !self.in_line_comment { if trimmed.ends_with('{') { self.indent += 1; } @@ -219,4 +229,13 @@ mod tests { ); assert_eq!(s.s, "function() {\n x\n}"); } + + #[test] + fn literal_text_does_not_change_indentation() { + let mut s = Source::default(); + s.indent(1); + s.push_str_literal("}\n{"); + s.deindent(1); + assert_eq!(s.s, " }\n {"); + } } diff --git a/crates/markdown/src/lib.rs b/crates/markdown/src/lib.rs index 706023c95..17a42fdbb 100644 --- a/crates/markdown/src/lib.rs +++ b/crates/markdown/src/lib.rs @@ -444,7 +444,7 @@ impl InterfaceGenerator<'_> { None => "\n", }; for line in docs.lines() { - self.push_str(line.trim()); + self.r#gen.src.push_str_literal(line.trim()); self.push_str("\n"); } } diff --git a/crates/markdown/tests/codegen.rs b/crates/markdown/tests/codegen.rs new file mode 100644 index 000000000..c3b8de70f --- /dev/null +++ b/crates/markdown/tests/codegen.rs @@ -0,0 +1,28 @@ +use wit_bindgen_core::{Files, wit_parser::Resolve}; + +#[test] +fn doc_line_starting_with_closing_brace() { + const WIT: &str = r#" + package a:b; + + world w { + export x: interface { + record r { + /// } + f: u32, + } + } + } + "#; + + let mut resolve = Resolve::default(); + let package = resolve.push_str("test.wit", WIT).unwrap(); + let world = resolve.select_world(&[package], Some("w")).unwrap(); + let mut files = Files::default(); + let mut generator = wit_bindgen_markdown::Opts::default().build(); + + generator.generate(&mut resolve, world, &mut files).unwrap(); + + let markdown = String::from_utf8(files.remove("w.md").unwrap()).unwrap(); + assert!(markdown.contains("\n

}\n")); +}