Add meta description tag to docs pages (#35112)

Closes #ISSUE

Adds basic frontmatter support to `.md` files in docs. The only
supported keys currently are `description` which becomes a `<meta
name="description" contents="...">` tag, and `title` which becomes a
normal `title` tag, with the title contents prefixed with the subject of
the file.

An example of the syntax can be found in `git.md`, as well as below

```md
---
title: Some more detailed title for this page
description: A page-specific description
---

# Editor
```

The above will be transformed into (with non-relevant tags removed)

```html
<head>
    <title>Editor | Some more detailed title for this page</title>
    <meta name="description" contents="A page-specific description">
</head>
<body>
<h1>Editor</h1>
</body>
```

If no front-matter is provided, or If one or both keys aren't provided,
the title and description will be set based on the `default-title` and
`default-description` keys in `book.toml` respectively.

## Implementation details

Unfortunately, `mdbook` does not support post-processing like it does
pre-processing, and only supports defining one description to put in the
meta tag per book rather than per file. So in order to apply
post-processing (necessary to modify the html head tags) the global book
description is set to a marker value `#description#` and the html
renderer is replaced with a sub-command of `docs_preprocessor` that
wraps the builtin `html` renderer and applies post-processing to the
`html` files, replacing the marker value and the `<title>(.*)</title>`
with the contents of the front-matter if there is one.

## Known limitations

The front-matter parsing is extremely simple, which avoids needing to
take on an additional dependency, or implement full yaml parsing.

* Double quotes and multi-line values are not supported, i.e. Keys and
values must be entirely on the same line, with no double quotes around
the value.

The following will not work:

```md
---
title: Some
 Multi-line
 Title
---
```

* The front-matter must be at the top of the file, with only white-space
preceding it

* The contents of the title and description will not be html-escaped.
They should be simple ascii text with no unicode or emoji characters

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Katie Greer <katie@zed.dev>
This commit is contained in:
Ben Kunkle 2025-07-29 18:01:03 -05:00 committed by GitHub
parent 57766199cf
commit 3824751e61
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 318 additions and 49 deletions

View file

@ -21,6 +21,8 @@ const ANSI_MAGENTA: &str = "\x1b[35m";
/// Whether stdout output is enabled.
static mut ENABLED_SINKS_STDOUT: bool = false;
/// Whether stderr output is enabled.
static mut ENABLED_SINKS_STDERR: bool = false;
/// Is Some(file) if file output is enabled.
static ENABLED_SINKS_FILE: Mutex<Option<std::fs::File>> = Mutex::new(None);
@ -45,6 +47,12 @@ pub fn init_output_stdout() {
}
}
pub fn init_output_stderr() {
unsafe {
ENABLED_SINKS_STDERR = true;
}
}
pub fn init_output_file(
path: &'static PathBuf,
path_rotate: Option<&'static PathBuf>,
@ -115,6 +123,21 @@ pub fn submit(record: Record) {
},
record.message
);
} else if unsafe { ENABLED_SINKS_STDERR } {
let mut stdout = std::io::stderr().lock();
_ = writeln!(
&mut stdout,
"{} {ANSI_BOLD}{}{}{ANSI_RESET} {} {}",
chrono::Local::now().format("%Y-%m-%dT%H:%M:%S%:z"),
LEVEL_ANSI_COLORS[record.level as usize],
LEVEL_OUTPUT_STRINGS[record.level as usize],
SourceFmt {
scope: record.scope,
module_path: record.module_path,
ansi: true,
},
record.message
);
}
let mut file = ENABLED_SINKS_FILE.lock().unwrap_or_else(|handle| {
ENABLED_SINKS_FILE.clear_poison();

View file

@ -5,7 +5,7 @@ mod env_config;
pub mod filter;
pub mod sink;
pub use sink::{flush, init_output_file, init_output_stdout};
pub use sink::{flush, init_output_file, init_output_stderr, init_output_stdout};
pub const SCOPE_DEPTH_MAX: usize = 4;