Skip to content

Rework note blocks and change admonition rendering #1754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 9, 2025
Merged
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
5 changes: 4 additions & 1 deletion docs/authoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,12 @@ Admonitions use a style similar to GitHub-flavored markdown, where the style nam
```markdown
> [!WARNING]
> This is a warning.

> [!NOTE]
> This is a note.
```

All this does is apply a CSS class to the blockquote. You should define the color or style of the rule in the [`theme/reference.css`](https://github.com/rust-lang/reference/blob/master/theme/reference.css) file if it isn't already defined.
The color and styling is defined in [`theme/reference.css`](https://github.com/rust-lang/reference/blob/master/theme/reference.css) and the transformation and icons are in [`mdbook-spec/src/lib.rs`](https://github.com/rust-lang/reference/blob/HEAD/mdbook-spec/src/lib.rs).

## Style

Expand Down
32 changes: 24 additions & 8 deletions mdbook-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,22 +144,38 @@ impl Spec {
/// > ...
/// ```
///
/// This will add a `<div class="warning">` around the blockquote so that
/// it can be styled differently. Any text between the brackets that can
/// be a CSS class is valid. The actual styling needs to be added in a CSS
/// file.
fn admonitions(&self, chapter: &Chapter) -> String {
/// This will add a `<div class="alert alert-warning">` around the
/// blockquote so that it can be styled differently, and injects an icon.
/// The actual styling needs to be added in the `reference.css` CSS file.
fn admonitions(&self, chapter: &Chapter, diag: &mut Diagnostics) -> String {
ADMONITION_RE
.replace_all(&chapter.content, |caps: &Captures<'_>| {
let lower = caps["admon"].to_lowercase();
let term = to_initial_case(&caps["admon"]);
let blockquote = &caps["blockquote"];
let initial_spaces = blockquote.chars().position(|ch| ch != ' ').unwrap_or(0);
let space = &blockquote[..initial_spaces];
// These icons are from GitHub, MIT License, see https://github.com/primer/octicons
let svg = match lower.as_str() {
"note" => "<path d=\"M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z\"></path>",
"warning" => "<path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"></path>",
_ => {
warn_or_err!(
diag,
"admonition `{lower}` in {:?} is incorrect or not yet supported",
chapter.path.as_ref().unwrap()
);
""
}
};
format!(
"{space}<div class=\"{lower}\">\n\
"{space}<div class=\"alert alert-{lower}\">\n\
\n\
{space}> ***{term}:***\n\
{space}> <p class=\"alert-title\">\
<svg viewBox=\"0 0 16 16\" width=\"18\" height=\"18\">\
{svg}\
</svg>{term}</p>\n\
{space} >\n\
{blockquote}\n\
\n\
{space}</div>\n",
Expand Down Expand Up @@ -226,7 +242,7 @@ impl Preprocessor for Spec {
if ch.is_draft_chapter() {
return;
}
ch.content = self.admonitions(&ch);
ch.content = self.admonitions(&ch, &mut diag);
ch.content = self.auto_link_references(&ch, &rules);
ch.content = self.render_rule_definitions(&ch.content, &tests, &git_ref);
if ch.name == "Test summary" {
Expand Down
4 changes: 2 additions & 2 deletions src/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ struct S {
pub fn f() {}
```

> Note: `rustc` currently recognizes the tools "clippy", "rustfmt", "diagnostic",
> "miri" and "rust_analyzer".
> [!NOTE]
> `rustc` currently recognizes the tools "clippy", "rustfmt", "diagnostic", "miri" and "rust_analyzer".

r[attributes.builtin]
## Built-in attributes index
Expand Down
35 changes: 14 additions & 21 deletions src/attributes/codegen.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ The *`inline` [attribute]* suggests that a copy of the attributed function
should be placed in the caller, rather than generating code to call the
function where it is defined.

> ***Note***: The `rustc` compiler automatically inlines functions based on
> internal heuristics. Incorrectly inlining functions can make the program
> slower, so this attribute should be used with care.
> [!NOTE]
> The `rustc` compiler automatically inlines functions based on internal heuristics. Incorrectly inlining functions can make the program slower, so this attribute should be used with care.

r[attributes.codegen.inline.modes]
There are three ways to use the inline attribute:
Expand All @@ -39,8 +38,8 @@ There are three ways to use the inline attribute:
* `#[inline(never)]` *suggests* that an inline expansion should never be
performed.

> ***Note***: `#[inline]` in every form is a hint, with no *requirements*
> on the language to place a copy of the attributed function in the caller.
> [!NOTE]
> `#[inline]` in every form is a hint, with no *requirements* on the language to place a copy of the attributed function in the caller.

r[attributes.codegen.cold]
### The `cold` attribute
Expand Down Expand Up @@ -229,8 +228,8 @@ Reference Manual], or elsewhere on [developer.arm.com].
[ARM Architecture Reference Manual]: https://developer.arm.com/documentation/ddi0487/latest
[developer.arm.com]: https://developer.arm.com

> ***Note***: The following pairs of features should both be marked as enabled
> or disabled together if used:
> [!NOTE]
> The following pairs of features should both be marked as enabled or disabled together if used:
> - `paca` and `pacg`, which LLVM currently implements as one feature.


Expand Down Expand Up @@ -390,10 +389,8 @@ r[attributes.codegen.target_feature.remark-rt]
See the [`is_x86_feature_detected`] or [`is_aarch64_feature_detected`] macros
in the standard library for runtime feature detection on these platforms.

> Note: `rustc` has a default set of features enabled for each target and CPU.
> The CPU may be chosen with the [`-C target-cpu`] flag. Individual features
> may be enabled or disabled for an entire crate with the
> [`-C target-feature`] flag.
> [!NOTE]
> `rustc` has a default set of features enabled for each target and CPU. The CPU may be chosen with the [`-C target-cpu`] flag. Individual features may be enabled or disabled for an entire crate with the [`-C target-feature`] flag.

r[attributes.codegen.track_caller]
## The `track_caller` attribute
Expand Down Expand Up @@ -427,11 +424,11 @@ fn f() {
}
```

> Note: `core` provides [`core::panic::Location::caller`] for observing caller locations. It wraps
> the [`core::intrinsics::caller_location`] intrinsic implemented by `rustc`.
> [!NOTE]
> `core` provides [`core::panic::Location::caller`] for observing caller locations. It wraps the [`core::intrinsics::caller_location`] intrinsic implemented by `rustc`.

> Note: because the resulting `Location` is a hint, an implementation may halt its walk up the stack
> early. See [Limitations](#limitations) for important caveats.
> [!NOTE]
> Because the resulting `Location` is a hint, an implementation may halt its walk up the stack early. See [Limitations](#limitations) for important caveats.

#### Examples

Expand Down Expand Up @@ -504,12 +501,8 @@ appears to observers to have been called at the attributed function's definition
caller information across virtual calls. A common example of this coercion is the creation of a
trait object whose methods are attributed.

> Note: The aforementioned shim for function pointers is necessary because `rustc` implements
> `track_caller` in a codegen context by appending an implicit parameter to the function ABI, but
> this would be unsound for an indirect call because the parameter is not a part of the function's
> type and a given function pointer type may or may not refer to a function with the attribute. The
> creation of a shim hides the implicit parameter from callers of the function pointer, preserving
> soundness.
> [!NOTE]
> The aforementioned shim for function pointers is necessary because `rustc` implements `track_caller` in a codegen context by appending an implicit parameter to the function ABI, but this would be unsound for an indirect call because the parameter is not a part of the function's type and a given function pointer type may or may not refer to a function with the attribute. The creation of a shim hides the implicit parameter from callers of the function pointer, preserving soundness.

[_MetaListNameValueStr_]: ../attributes.md#meta-item-attribute-syntax
[`-C target-cpu`]: ../../rustc/codegen-options/index.html#target-cpu
Expand Down
3 changes: 2 additions & 1 deletion src/attributes/debugger.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ r[attributes.debugger.collapse_debuginfo.default]
The `external` behavior is the default for macros that don't have this attribute, unless they are built-in macros.
For built-in macros the default is `yes`.

> **Note**: `rustc` has a `-C collapse-macro-debuginfo` CLI option to override both the default collapsing behavior and `#[collapse_debuginfo]` attributes.
> [!NOTE]
> `rustc` has a `-C collapse-macro-debuginfo` CLI option to override both the default collapsing behavior and `#[collapse_debuginfo]` attributes.

```rust
#[collapse_debuginfo(yes)]
Expand Down
29 changes: 14 additions & 15 deletions src/attributes/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ r[attributes.diagnostics.lint.forbid]
* `#[forbid(C)]` is the same as `deny(C)`, but also forbids changing the lint
level afterwards,

> Note: The lint checks supported by `rustc` can be found via `rustc -W help`,
> along with their default settings and are documented in the [rustc book].
> [!NOTE]
> The lint checks supported by `rustc` can be found via `rustc -W help`, along with their default settings and are documented in the [rustc book].

```rust
pub mod m1 {
Expand Down Expand Up @@ -98,9 +98,8 @@ pub mod m3 {
}
```

> Note: `rustc` allows setting lint levels on the
> [command-line][rustc-lint-cli], and also supports [setting
> caps][rustc-lint-caps] on the lints that are reported.
> [!NOTE]
> `rustc` allows setting lint levels on the [command-line][rustc-lint-cli], and also supports [setting caps][rustc-lint-caps] on the lints that are reported.

r[attributes.diagnostics.lint.reason]
### Lint Reasons
Expand Down Expand Up @@ -222,8 +221,8 @@ pub fn another_example() {
}
```

> Note: The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently
> defined to always generate the `unfulfilled_lint_expectations` lint.
> [!NOTE]
> The behavior of `#[expect(unfulfilled_lint_expectations)]` is currently defined to always generate the `unfulfilled_lint_expectations` lint.

r[attributes.diagnostics.lint.group]
### Lint groups
Expand Down Expand Up @@ -297,7 +296,8 @@ fn foo() {
}
```

> Note: `rustc` currently recognizes the tool lints for "[clippy]" and "[rustdoc]".
> [!NOTE]
> `rustc` currently recognizes the tool lints for "[clippy]" and "[rustdoc]".

r[attributes.diagnostics.deprecated]
## The `deprecated` attribute
Expand Down Expand Up @@ -433,10 +433,8 @@ impl Trait for i32 {
r[attributes.diagnostics.must_use.trait-impl-function]
When used on a function in a trait implementation, the attribute does nothing.

> Note: Trivial no-op expressions containing the value will not violate the
> lint. Examples include wrapping the value in a type that does not implement
> [`Drop`] and then not using that type and being the final expression of a
> [block expression] that is not used.
> [!NOTE]
> Trivial no-op expressions containing the value will not violate the lint. Examples include wrapping the value in a type that does not implement [`Drop`] and then not using that type and being the final expression of a [block expression] that is not used.
>
> ```rust
> #[must_use]
Expand All @@ -452,8 +450,8 @@ When used on a function in a trait implementation, the attribute does nothing.
> };
> ```

> Note: It is idiomatic to use a [let statement] with a pattern of `_`
> when a must-used value is purposely discarded.
> [!NOTE]
> It is idiomatic to use a [let statement] with a pattern of `_` when a must-used value is purposely discarded.
>
> ```rust
> #[must_use]
Expand Down Expand Up @@ -558,7 +556,8 @@ r[attributes.diagnostic.do_not_recommend]
r[attributes.diagnostic.do_not_recommend.intro]
The `#[diagnostic::do_not_recommend]` attribute is a hint to the compiler to not show the annotated trait implementation as part of a diagnostic message.

> **Note**: Suppressing the recommendation can be useful if you know that the recommendation would normally not be useful to the programmer. This often occurs with broad, blanket impls. The recommendation may send the programmer down the wrong path, or the trait implementation may be an internal detail that you don't want to expose, or the bounds may not be able to be satisfied by the programmer.
> [!NOTE]
> Suppressing the recommendation can be useful if you know that the recommendation would normally not be useful to the programmer. This often occurs with broad, blanket impls. The recommendation may send the programmer down the wrong path, or the trait implementation may be an internal detail that you don't want to expose, or the bounds may not be able to be satisfied by the programmer.
>
> For example, in an error message about a type not implementing a required trait, the compiler may find a trait implementation that would satisfy the requirements if it weren't for specific bounds in the trait implementation. The compiler may tell the user that there is an impl, but the problem is the bounds in the trait implementation. The `#[diagnostic::do_not_recommend]` attribute can be used to tell the compiler to *not* tell the user about the trait implementation, and instead simply tell the user the type doesn't implement the required trait.

Expand Down
9 changes: 6 additions & 3 deletions src/attributes/limits.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ r[attributes.limits.recursion_limit.syntax]
It uses the [_MetaNameValueStr_]
syntax to specify the recursion depth.

> Note: The default in `rustc` is 128.
> [!NOTE]
> The default in `rustc` is 128.

```rust,compile_fail
#![recursion_limit = "4"]
Expand Down Expand Up @@ -44,7 +45,8 @@ r[attributes.limits.type_length_limit]
## The `type_length_limit` attribute


> **Note**: This limit is only enforced when the nightly `-Zenforce-type-length-limit` flag is active.
> [!NOTE]
> This limit is only enforced when the nightly `-Zenforce-type-length-limit` flag is active.
>
> For more information, see <https://github.com/rust-lang/rust/pull/127670>.

Expand All @@ -56,7 +58,8 @@ r[attributes.limits.type_length_limit.syntax]
It is applied at the [crate] level, and uses the [_MetaNameValueStr_] syntax
to set the limit based on the number of type substitutions.

> Note: The default in `rustc` is 1048576.
> [!NOTE]
> The default in `rustc` is 1048576.

```rust,ignore
#![type_length_limit = "4"]
Expand Down
8 changes: 4 additions & 4 deletions src/attributes/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ Test functions must be free, monomorphic functions that take no arguments, and t
<!-- If the previous section needs updating (from "must take no arguments"
onwards, also update it in the crates-and-source-files.md file -->

> Note: The test mode is enabled by passing the `--test` argument to `rustc`
> or using `cargo test`.
> [!NOTE]
> The test mode is enabled by passing the `--test` argument to `rustc` or using `cargo test`.

r[attributes.testing.test.success]
The test harness calls the returned value's [`report`] method, and classifies the test as passed or failed depending on whether the resulting [`ExitCode`] represents successful termination.
Expand Down Expand Up @@ -69,8 +69,8 @@ fn mytest() {
}
```

> **Note**: The `rustc` test harness supports the `--include-ignored` flag to
> force ignored tests to be run.
> [!NOTE]
> The `rustc` test harness supports the `--include-ignored` flag to force ignored tests to be run.

r[attributes.testing.should_panic]
## The `should_panic` attribute
Expand Down
11 changes: 4 additions & 7 deletions src/behavior-considered-undefined.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,8 @@ r[undefined.runtime]
* For assumptions specifically related to unwinding, see the [panic documentation][unwinding-ffi].
* The runtime assumes that a Rust stack frame is not deallocated without executing destructors for local variables owned by the stack frame. This assumption can be violated by C functions like `longjmp`.

> **Note**: Undefined behavior affects the entire program. For example, calling
> a function in C that exhibits undefined behavior of C means your entire
> program contains undefined behaviour that can also affect the Rust code. And
> vice versa, undefined behavior in Rust can cause adverse affects on code
> executed by any FFI calls to other languages.
> [!NOTE]
> Undefined behavior affects the entire program. For example, calling a function in C that exhibits undefined behavior of C means your entire program contains undefined behaviour that can also affect the Rust code. And vice versa, undefined behavior in Rust can cause adverse affects on code executed by any FFI calls to other languages.

r[undefined.pointed-to]
### Pointed-to bytes
Expand Down Expand Up @@ -237,8 +234,8 @@ r[undefined.validity.valid-range]
* If a type has a custom range of a valid values, then a valid value must be in that range.
In the standard library, this affects [`NonNull<T>`] and [`NonZero<T>`].

> **Note**: `rustc` achieves this with the unstable
> `rustc_layout_scalar_valid_range_*` attributes.
> [!NOTE]
> `rustc` achieves this with the unstable `rustc_layout_scalar_valid_range_*` attributes.

r[undefined.validity.undef]
**Note:** Uninitialized memory is also implicitly invalid for any type that has
Expand Down
10 changes: 4 additions & 6 deletions src/comments.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,11 @@ modules that occupy a source file.
r[comments.doc.bare-crs]
The character `U+000D` (CR) is not allowed in doc comments.

> **Note**: It is conventional for doc comments to contain Markdown, as expected by
> `rustdoc`. However, the comment syntax does not respect any internal Markdown.
> ``/** `glob = "*/*.rs";` */`` terminates the comment at the first `*/`, and the
> remaining code would cause a syntax error. This slightly limits the content of
> block doc comments compared to line doc comments.
> [!NOTE]
> It is conventional for doc comments to contain Markdown, as expected by `rustdoc`. However, the comment syntax does not respect any internal Markdown. ``/** `glob = "*/*.rs";` */`` terminates the comment at the first `*/`, and the remaining code would cause a syntax error. This slightly limits the content of block doc comments compared to line doc comments.

> **Note**: The sequence `U+000D` (CR) immediately followed by `U+000A` (LF) would have been previously transformed into a single `U+000A` (LF).
> [!NOTE]
> The sequence `U+000D` (CR) immediately followed by `U+000A` (LF) would have been previously transformed into a single `U+000A` (LF).

## Examples

Expand Down
Loading