Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion crates/mdbook-html/src/html/hide_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ fn partition_rust_source(s: &str) -> (&str, &str) {
r"^(?mx)
(
(?:
^[ \t]*\#!\[.* (?:\r?\n)?
^[ \t]*(?:\#\x20)?[ \t]*\#!\[.* (?:\r?\n)?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this have \x20? This doesn't seem to have the same understanding of hidden lines as the rest of the code does.

Also, this seems to not also update the blank lines rule.

I would expect the following to work:

Input Output Hidden
#!feature(x) #!feature(x) Not hidden
##!feature(x) #!feature(x) Not hidden
# #![feature(x) #!feature(x) Hidden
# #![feature(x)
#
# #![feature(y)]
#![feature(x)

#![feature(y)]
Hidden

Perhaps it would be best to extract the hide-lines logic from hide_lines_rust so that there could be an iterator over the rust source lines that indicates if a line is hidden or not, and then these different parts could reuse that logic. rustdoc does something like this here with an enum that represents whether a line is hidden.

|
^\s* (?:\r?\n)?
)*
Expand All @@ -155,6 +155,36 @@ fn partition_rust_source(s: &str) -> (&str, &str) {
s.split_at(split_idx)
}

#[test]
fn wrap_rust_main_basic() {
// Code without fn main gets wrapped
assert_eq!(
wrap_rust_main("let x = 1;"),
Some("# #![allow(unused)]\n# fn main() {\nlet x = 1;\n# }".to_string())
);
}

#[test]
fn wrap_rust_main_with_feature_attr() {
// Crate-level attributes should be placed before fn main (issue #2640)
// Without hidden prefix:
assert_eq!(
wrap_rust_main("#![feature(rustc_attrs)]\n#[rustc_on_unimplemented = \"oh no\"]\npub trait Foo {}"),
Some("# #![allow(unused)]\n#![feature(rustc_attrs)]\n# fn main() {\n#[rustc_on_unimplemented = \"oh no\"]\npub trait Foo {}\n# }".to_string())
);
// With hidden line prefix `# ` (the actual input from markdown):
assert_eq!(
wrap_rust_main("# #![feature(rustc_attrs)]\n#[rustc_on_unimplemented = \"oh no\"]\npub trait Foo {}"),
Some("# #![allow(unused)]\n# #![feature(rustc_attrs)]\n# fn main() {\n#[rustc_on_unimplemented = \"oh no\"]\npub trait Foo {}\n# }".to_string())
);
}

#[test]
fn wrap_rust_main_already_has_main() {
// Code with fn main should not be wrapped
assert_eq!(wrap_rust_main("fn main() {}"), None);
}

#[test]
fn it_partitions_rust_source() {
assert_eq!(partition_rust_source(""), ("", ""));
Expand Down Expand Up @@ -190,4 +220,9 @@ fn it_partitions_rust_source() {
partition_rust_source(" // Example"),
("", " // Example")
);
// Hidden line prefix with crate attribute (issue #2640)
assert_eq!(
partition_rust_source("# #![feature(rustc_attrs)]\n#[foo]\npub trait Foo {}"),
("# #![feature(rustc_attrs)]\n", "#[foo]\npub trait Foo {}")
);
}
19 changes: 19 additions & 0 deletions tests/testsuite/playground.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ fn playground_on_rust_code() {
);
}

// Verifies that hidden crate-level attributes (like #![feature(...)]) are
// properly wrapped when fn main is generated. The attributes should appear
// before fn main, not inside it. (issue #2640)
#[test]
fn playground_hidden_feature_attr() {
BookTest::from_dir("playground/playground_hidden_feature_attr").check_main_file(
"book/feature-attr.html",
str![[r##"
<h1 id="feature-attr"><a class="header" href="#feature-attr">Feature Attr</a></h1>
<pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">#![feature(rustc_attrs)]
</span><span class="boring">fn main() {
</span>#[rustc_on_unimplemented = "oh no"]
pub trait Foo {}
<span class="boring">}</span></code></pre>
"##]],
);
}

// When the playground is disabled, there should be no playground class.
#[test]
fn disabled_playground() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[book]
title = "playground_on_rust_code"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Summary

[Hidden Feature Attr](feature-attr.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Feature Attr

```rust
# #![feature(rustc_attrs)]
#[rustc_on_unimplemented = "oh no"]
pub trait Foo {}
```