rust/compiler
bors 41bafc4ff3 Auto merge of #110800 - GuillaumeGomez:custom_code_classes_in_docs, r=t-rustdoc
Accept additional user-defined syntax classes in fenced code blocks

Part of #79483.

This is a re-opening of https://github.com/rust-lang/rust/pull/79454 after a big update/cleanup. I also converted the syntax to pandoc as suggested by `@notriddle:` the idea is to be as compatible as possible with the existing instead of having our own syntax.

## Motivation

From the original issue: https://github.com/rust-lang/rust/issues/78917

> The technique used by `inline-c-rs` can be ported to other languages. It's just super fun to see C code inside Rust documentation that is also tested by `cargo doc`. I'm sure this technique can be used by other languages in the future.

Having custom CSS classes for syntax highlighting will allow tools like `highlight.js` to be used in order to provide highlighting for languages other than Rust while not increasing technical burden on rustdoc.

## What is the feature about?

In short, this PR changes two things, both related to codeblocks in doc comments in Rust documentation:

 * Allow to disable generation of `language-*` CSS classes with the `custom` attribute.
 * Add your own CSS classes to a code block so that you can use other tools to highlight them.

#### The `custom` attribute

Let's start with the new `custom` attribute: it will disable the generation of the `language-*` CSS class on the generated HTML code block. For example:

```rust
/// ```custom,c
/// int main(void) {
///     return 0;
/// }
/// ```
```

The generated HTML code block will not have `class="language-c"` because the `custom` attribute has been set. The `custom` attribute becomes especially useful with the other thing added by this feature: adding your own CSS classes.

#### Adding your own CSS classes

The second part of this feature is to allow users to add CSS classes themselves so that they can then add a JS library which will do it (like `highlight.js` or `prism.js`), allowing to support highlighting for other languages than Rust without increasing burden on rustdoc. To disable the automatic `language-*` CSS class generation, you need to use the `custom` attribute as well.

This allow users to write the following:

```rust
/// Some code block with `{class=language-c}` as the language string.
///
/// ```custom,{class=language-c}
/// int main(void) {
///     return 0;
/// }
/// ```
fn main() {}
```

This will notably produce the following HTML:

```html
<pre class="language-c">
int main(void) {
    return 0;
}</pre>
```

Instead of:

```html
<pre class="rust rust-example-rendered">
<span class="ident">int</span> <span class="ident">main</span>(<span class="ident">void</span>) {
    <span class="kw">return</span> <span class="number">0</span>;
}
</pre>
```

To be noted, we could have written `{.language-c}` to achieve the same result. `.` and `class=` have the same effect.

One last syntax point: content between parens (`(like this)`) is now considered as comment and is not taken into account at all.

In addition to this, I added an `unknown` field into `LangString` (the parsed code block "attribute") because of cases like this:

```rust
/// ```custom,class:language-c
/// main;
/// ```
pub fn foo() {}
```

Without this `unknown` field, it would generate in the DOM: `<pre class="language-class:language-c language-c">`, which is quite bad. So instead, it now stores all unknown tags into the `unknown` field and use the first one as "language". So in this case, since there is no unknown tag, it'll simply generate `<pre class="language-c">`. I added tests to cover this.

Finally, I added a parser for the codeblock attributes to make it much easier to maintain. It'll be pretty easy to extend.

As to why this syntax for adding attributes was picked: it's [Pandoc's syntax](https://pandoc.org/MANUAL.html#extension-fenced_code_attributes). Even if it seems clunkier in some cases, it's extensible, and most third-party Markdown renderers are smart enough to ignore Pandoc's brace-delimited attributes (from [this comment](https://github.com/rust-lang/rust/pull/110800#issuecomment-1522044456)).

## Raised concerns

#### It's not obvious when the `language-*` attribute generation will be added or not.

It is added by default. If you want to disable it, you will need to use the `custom` attribute.

#### Why not using HTML in markdown directly then?

Code examples in most languages are likely to contain `<`, `>`, `&` and `"` characters. These characters [require escaping](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/pre) when written inside the `<pre>` element. Using the \`\`\` code blocks allows rustdoc to take care of escaping, which means doc authors can paste code samples directly without manually converting them to HTML.

cc `@poliorcetics`
r? `@notriddle`
2023-09-16 13:10:11 +00:00
..
rustc inline format!() args up to and including rustc_middle 2023-07-30 13:18:33 +02:00
rustc_abi turns out Layout has some more things to worry about -- move ABI comparison into helper function 2023-09-08 09:14:07 +02:00
rustc_arena Bump cfg(bootstrap) 2023-08-23 20:05:14 -04:00
rustc_ast Move let expression checking to parsing 2023-09-11 15:51:18 +00:00
rustc_ast_lowering Auto merge of #115677 - matthewjasper:let-expr-recovery, r=b-naber 2023-09-14 19:56:55 +00:00
rustc_ast_passes Move let expression checking to parsing 2023-09-11 15:51:18 +00:00
rustc_ast_pretty Move let expression checking to parsing 2023-09-11 15:51:18 +00:00
rustc_attr Auto merge of #114201 - Centri3:explicit-repr-rust, r=WaffleLapkin 2023-08-25 00:02:54 +00:00
rustc_baked_icu_data Regen baked data 2023-05-02 10:45:16 -07:00
rustc_borrowck cleanup on messages 2023-09-12 07:27:17 +08:00
rustc_builtin_macros Fix invalid markdown codeblock label 2023-09-16 11:37:41 +02:00
rustc_codegen_cranelift make it more clear which functions create fresh AllocId 2023-09-14 07:27:31 +02:00
rustc_codegen_gcc treat host effect params as erased generics in codegen 2023-09-14 07:34:35 +00:00
rustc_codegen_llvm Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk 2023-09-14 13:42:30 +00:00
rustc_codegen_ssa Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk 2023-09-14 13:42:30 +00:00
rustc_const_eval make interpreter type Debug impl independent of Ty debug impl 2023-09-15 09:54:06 +02:00
rustc_data_structures Bring back verbose_generic_activity_with_arg 2023-09-13 13:41:19 +02:00
rustc_driver Update rustix 2023-07-03 07:20:51 +00:00
rustc_driver_impl Auto merge of #115735 - bjorn3:better_list_crate_metadata, r=wesleywiser 2023-09-13 10:23:57 +00:00
rustc_error_codes Auto merge of #114656 - bossmc:rework-no-coverage-attr, r=oli-obk 2023-09-14 01:05:18 +00:00
rustc_error_messages Bump cfg(bootstrap) 2023-08-23 20:05:14 -04:00
rustc_errors Auto merge of #115418 - Zoxc:freeze-source, r=oli-obk 2023-09-08 17:20:23 +00:00
rustc_expand Enable incremental-relative-spans by default. 2023-09-07 20:21:13 +00:00
rustc_feature Auto merge of #110800 - GuillaumeGomez:custom_code_classes_in_docs, r=t-rustdoc 2023-09-16 13:10:11 +00:00
rustc_fluent_macro Fix diagnostics with errors 2023-05-26 10:44:18 +00:00
rustc_fs_util
rustc_graphviz enable rust_2018_idioms for doctests 2023-05-07 00:12:29 +03:00
rustc_hir Move let expression checking to parsing 2023-09-11 15:51:18 +00:00
rustc_hir_analysis Auto merge of #115853 - obeis:hir-analysis-migrate-diagnostics-6, r=compiler-errors 2023-09-15 11:55:27 +00:00
rustc_hir_pretty Auto merge of #114545 - fee1-dead-contrib:lower-impl-effect, r=oli-obk 2023-08-08 19:23:41 +00:00
rustc_hir_typeck Auto merge of #115315 - RalfJung:field-capture-packed-alignment, r=oli-obk 2023-09-16 05:29:23 +00:00
rustc_incremental Avoid a source_span query when encoding Spans into query results 2023-09-08 02:08:52 +02:00
rustc_index Auto merge of #115094 - Mark-Simulacrum:bootstrap-update, r=ozkanonur 2023-08-24 11:10:52 +00:00
rustc_infer Canonicalize effect vars in new solver 2023-09-15 05:11:16 +00:00
rustc_interface Auto merge of #115735 - bjorn3:better_list_crate_metadata, r=wesleywiser 2023-09-13 10:23:57 +00:00
rustc_lexer Update lexer emoji diagnostics to Unicode 15.0 2023-07-29 08:47:21 +08:00
rustc_lint Auto merge of #114494 - est31:extend_useless_ptr_null_checks, r=jackh726 2023-09-16 03:40:20 +00:00
rustc_lint_defs Auto merge of #112038 - Nemo157:edition-2024-unsafe_op_in_unsafe_fn, r=RalfJung 2023-09-14 11:52:08 +00:00
rustc_llvm llvm-wrapper: adapt for LLVM API changes 2023-09-15 14:31:43 +00:00
rustc_log inline format!() args up to and including rustc_middle 2023-07-30 13:18:33 +02:00
rustc_macros Bump cfg(bootstrap) 2023-08-23 20:05:14 -04:00
rustc_metadata Auto merge of #115735 - bjorn3:better_list_crate_metadata, r=wesleywiser 2023-09-13 10:23:57 +00:00
rustc_middle Auto merge of #110800 - GuillaumeGomez:custom_code_classes_in_docs, r=t-rustdoc 2023-09-16 13:10:11 +00:00
rustc_mir_build make it more clear which functions create fresh AllocId 2023-09-14 07:27:31 +02:00
rustc_mir_dataflow Support non-scalar constants. 2023-09-11 16:29:41 +00:00
rustc_mir_transform Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk 2023-09-14 13:42:30 +00:00
rustc_monomorphize Auto merge of #115804 - RalfJung:valtree-to-const-val, r=oli-obk 2023-09-14 15:34:31 +00:00
rustc_parse Auto merge of #115677 - matthewjasper:let-expr-recovery, r=b-naber 2023-09-14 19:56:55 +00:00
rustc_parse_format Replace data_structures dependency with index in rustc_parse_format 2023-09-05 19:11:50 +02:00
rustc_passes Auto merge of #114494 - est31:extend_useless_ptr_null_checks, r=jackh726 2023-09-16 03:40:20 +00:00
rustc_plugin_impl Add rustc_fluent_macro to decouple fluent from rustc_macros 2023-04-18 18:56:22 +00:00
rustc_privacy Rollup merge of #115727 - fee1-dead-contrib:effect-fallback, r=oli-obk 2023-09-11 17:03:31 +02:00
rustc_query_impl Remove verbose_generic_activity_with_arg 2023-09-10 17:47:16 +02:00
rustc_query_system Auto merge of #115388 - Zoxc:sharded-lock, r=SparrowLii 2023-09-11 01:43:29 +00:00
rustc_resolve Auto merge of #115677 - matthewjasper:let-expr-recovery, r=b-naber 2023-09-14 19:56:55 +00:00
rustc_serialize Use a specialized varint + bitpacking scheme for DepGraph encoding 2023-09-04 12:16:50 -04:00
rustc_session Auto merge of #115735 - bjorn3:better_list_crate_metadata, r=wesleywiser 2023-09-13 10:23:57 +00:00
rustc_smir Rollup merge of #115772 - ouz-a:smir_span2, r=oli-obk 2023-09-14 19:12:31 +02:00
rustc_span Auto merge of #110800 - GuillaumeGomez:custom_code_classes_in_docs, r=t-rustdoc 2023-09-16 13:10:11 +00:00
rustc_symbol_mangling Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk 2023-09-14 13:42:30 +00:00
rustc_target special case TyAndLayout debug impl 2023-09-15 22:57:07 +02:00
rustc_trait_selection Canonicalize effect vars in new solver 2023-09-15 05:11:16 +00:00
rustc_traits remove some unused crate deps 2023-09-01 19:13:09 +03:00
rustc_transmute make the eval() functions on our const types return the resulting value 2023-09-13 07:29:34 +02:00
rustc_ty_utils Auto merge of #115817 - fee1-dead-contrib:fix-codegen, r=oli-obk 2023-09-14 13:42:30 +00:00
rustc_type_ir Explain why TypeFoldable is a sub-trait of TypeVisitable. 2023-09-13 16:50:35 +10:00