Split example file docblock and code when generating web examples markdown (#18191)

# Objective

Separate example explanation (file docblock) and the code so they can be
layout differently in the website and we can give a higher importance to
the explanation on the [website search
tool](https://github.com/bevyengine/bevy-website/pull/1935). This would
also allow us to improve the examples so they become even more like a
cookbook.

## Solution

Update the `example-showcase` tool to extract the example file docblock
and write it as the example markdown content. This allows us to access
the explanation via `page.content` in Zola.

## Testing

I've checked that the output is correct after running the tool and it
doesn't throw any error. I've also validated that the approach will work
on the website.

## Showcase

This is a quick and dirty example of what we could do in the web
examples after the change. When we implement the real thing we can put
the explanation on a sidebar or explore other layout options.

<img width="1362" alt="image"
src="https://github.com/user-attachments/assets/6738542e-31c3-41cd-972a-7fa2e942e85d"
/>
This commit is contained in:
Asier Illarramendi 2025-03-19 21:01:37 +01:00 committed by GitHub
parent 06bae05ba2
commit faef6d18e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -548,7 +548,9 @@ weight = {}
let _ = fs::create_dir_all(&example_path);
let code_path = example_path.join(Path::new(&to_show.path).file_name().unwrap());
let _ = fs::copy(&to_show.path, &code_path);
let code = fs::read_to_string(&to_show.path).unwrap();
let (docblock, code) = split_docblock_and_code(&code);
let _ = fs::write(&code_path, code);
let mut example_index = File::create(example_path.join("index.md")).unwrap();
example_index
@ -572,7 +574,10 @@ code_path = \"content/examples{}/{}\"
shader_code_paths = {:?}
github_code_path = \"{}\"
header_message = \"Examples ({})\"
+++",
+++
{}
",
to_show.name,
match api {
WebApi::Webgpu => "-webgpu",
@ -610,6 +615,7 @@ header_message = \"Examples ({})\"
WebApi::Webgpu => "WebGPU",
WebApi::Webgl2 => "WebGL2",
},
docblock,
)
.as_bytes(),
)
@ -731,6 +737,23 @@ header_message = \"Examples ({})\"
}
}
fn split_docblock_and_code(code: &str) -> (String, &str) {
let mut docblock_lines = Vec::new();
let mut code_byte_start = 0;
for line in code.lines() {
if line.starts_with("//!") {
docblock_lines.push(line.trim_start_matches("//!").trim());
} else if !line.trim().is_empty() {
break;
}
code_byte_start += line.len() + 1;
}
(docblock_lines.join("\n"), &code[code_byte_start..])
}
fn parse_examples() -> Vec<Example> {
let manifest_file = fs::read_to_string("Cargo.toml").unwrap();
let manifest = manifest_file.parse::<DocumentMut>().unwrap();