about summary refs log tree commit diff
path: root/src/librustdoc/html/markdown.rs
AgeCommit message (Collapse)AuthorLines
2024-09-22Strip last backline from non-rust code examplesGuillaume Gomez-1/+3
2024-09-05Rollup merge of #120736 - notriddle:notriddle/toc, r=t-rustdocMatthias Krüger-11/+62
rustdoc: add header map to the table of contents ## Summary Add header sections to the sidebar TOC. ### Preview ![image](https://github.com/user-attachments/assets/eae4df02-86aa-4df4-8c61-a95685cd8829) * http://notriddle.com/rustdoc-html-demo-9/toc/rust/std/index.html * http://notriddle.com/rustdoc-html-demo-9/toc/rust-derive-builder/derive_builder/index.html ## Motivation Some pages are very wordy, like these. | crate | word count | |--|--| | [std::option](https://doc.rust-lang.org/stable/std/option/index.html) | 2,138 | [derive_builder](https://docs.rs/derive_builder/0.13.0/derive_builder/index.html) | 2,403 | [tracing](https://docs.rs/tracing/0.1.40/tracing/index.html) | 3,912 | [regex](https://docs.rs/regex/1.10.3/regex/index.html) | 8,412 This kind of very long document is more navigable with a table of contents, like Wikipedia's or the one [GitHub recently added](https://github.blog/changelog/2021-04-13-table-of-contents-support-in-markdown-files/) for READMEs. In fact, the use case is so compelling, that it's been requested multiple times and implemented in an extension: * https://github.com/rust-lang/rust/issues/80858 * https://github.com/rust-lang/rust/issues/28056 * https://github.com/rust-lang/rust/issues/14475 * https://rust.extension.sh/#show-table-of-content (Some of these issues ask for more than this, so don’t close them.) It's also been implemented by hand in some crates, because the author really thought it was needed. Protip: for a more exhaustive list, run [`site:docs.rs table of contents`](https://duckduckgo.com/?t=ffab&q=site%3Adocs.rs+table+of+contents&ia=web), though some of them are false positives. * https://docs.rs/figment/0.10.14/figment/index.html#table-of-contents * https://docs.rs/csv/1.3.0/csv/tutorial/index.html#table-of-contents * https://docs.rs/axum/0.7.4/axum/response/index.html#table-of-contents * https://docs.rs/regex-automata/0.4.5/regex_automata/index.html#table-of-contents Unfortunately for these hand-built ToCs, because they're just part of the docs, there's no consistent way to turn them off if the reader doesn't want them. It's also more complicated to ensure they stay in sync with the docs they're supposed to describe, and they don't stay with you when you scroll like Wikipedia's [does now](https://uxdesign.cc/design-notes-on-the-2023-wikipedia-redesign-d6573b9af28d). ## Guide-level explanation When writing docs for a top-level item, the first and second level of headers will be shown in an outline in the sidebar. In this context, "top level" means "not associated". This means, if you're writing very long guides or explanations, and you want it to have a table of contents in the sidebar for its headings, the ideal place to attach it is usually the *module* or *crate*, because this page has fewer other things on it (and is the ideal place to describe "cross-cutting concerns" for its child items). If you're reading documentation, and want to get rid of the table of contents, open the ![image](https://github.com/rust-lang/rust/assets/1593513/2ad82466-5fe3-4684-b1c2-6be4c99a8666) Settings panel and checkmark "Hide table of contents." ## Reference-level explanation Top-level items have an outline generated. This works for potentially-malformed header trees by pairing a header with the nearest header with a higher level. For example: ```markdown ## A # B # C ## D ## E ``` A, B, and C are all siblings, and D and E are children of C. Rustdoc only presents two layers of tree, but it tracks up to the full depth of 6 while preparing it. That means that these two doc comment both generate the same outline: ```rust /// # First /// ## Second struct One; /// ## First /// ### Second struct Two; ``` ## Drawbacks The biggest drawback is adding more stuff to the sidebar. My crawl through docs.rs shows this to, surprisingly, be less of a problem than I thought. The manually-built tables of contents, and the pages with dozens of headers, usually seem to be modules or crates, not types (where extreme scrolling would become a problem, since they already have methods to deal with). The best example of a type with many headers is [vec::Vec](https://doc.rust-lang.org/1.75.0/std/vec/struct.Vec.html), which still only has five headers, not dozens like [axum::extract](https://docs.rs/axum/0.7.4/axum/extract/index.html). ## Rationale and alternatives ### Why in the existing sidebar? The method links and the top-doc header links have more in common with each other than either of them do with the "In [parent module]" links, and should go together. ### Why limited to two levels? The sidebar is pretty narrow, and I don't want too much space used by indentation. Making the sidebar wider, while it has some upsides, also takes up more space on middling-sized screens or tiled WMs. ### Why not line wrap? That behaves strangely when resizing. ## Prior art ### Doc generators that have TOC for headers https://hexdocs.pm/phoenix/Phoenix.Controller.html is very close, in the sense that it also has header sections directly alongside functions and types. Another example, referenced as part of the [early sidebar discussion](https://github.com/rust-lang/rust/issues/37856) that added methods, Ruby will show a table of contents in the sidebar (for example, on the [ARGF](https://docs.ruby-lang.org/en/master/ARGF.html) class). According to their changelog, [they added it in 2013](https://github.com/ruby/rdoc/blob/06137bde8ccc48cd502bc28178bcd8f2dfe37624/History.rdoc#400--2013-02-24-). Haskell seems to mix text and functions even more freely than Elixir. For example, this [Naming conventions](https://hackage.haskell.org/package/base-4.19.0.0/docs/Control-Monad.html#g:3) is plain text, and is immediately followed by functions. And the [Pandoc top level](https://hackage.haskell.org/package/pandoc-3.1.11.1/docs/Text-Pandoc.html) has items split up by function, rather than by kind. Their TOC matches exactly with the contents of the page. ### Doc generators that don't have header TOC, but still have headers Elm, interestingly enough, seems to have the same setup that Rust used to have: sibling navigation between modules, and no index within a single page. [They keep Haskell's habit of named sections with machine-generated type signatures](https://package.elm-lang.org/packages/elm/browser/latest/Browser-Dom), though. [PHP](https://www.php.net/manual/en/book.datetime.php), like elm, also has a right-hand sidebar with sibling navigation. However, PHP has a single page for a single method, unlike Rust's page for an entire "class." So even though these pages have headers, it's never more than ten at most. And when they have guides, those guides are also multi-page. ## Unresolved questions * Writing recommendations for anyone who wants to take advantage of this. * Right now, it does not line wrap. That might be a bad idea: a lot of these are getting truncated. * Split sidebars, which I [tried implementing](https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/Table.20of.20contents), are not required. The TOC can be turned off, if it's really a problem. Implemented in https://github.com/rust-lang/rust/pull/120818, but needs more, separate, discussion. ## Future possibilities I would like to do a better job of distinguishing global navigation from local navigation. Rustdoc has a pretty reasonable information architecture, if only we did a better job of communicating it. This PR aims, mostly, to help doc authors help their users by writing docs that can be more effectively skimmed. But it doesn't do anything to make it easier to tell the TOC and the Module Nav apart.
2024-08-30Remove `#[macro_use] extern crate tracing` from rustdoc.Nicholas Nethercote-0/+1
2024-08-20rustdoc: consistentify `#TOC` and `#ModNav` to lowercaseMichael Howell-2/+3
2024-08-20rustdoc: show code spans as `<code>` in TOCMichael Howell-2/+27
2024-08-20Add Top TOC support to rustdocMichael Howell-11/+36
This commit adds the headers for the top level documentation to rustdoc's existing table of contents, along with associated items. It only show two levels of headers. Going further would require the sidebar to be wider, and that seems unnecessary (the crates that have manually-built TOCs usually don't need deeply nested headers).
2024-08-20Remove unneeded conversion to `DefId` for `ExtraInfo`Guillaume Gomez-24/+20
2024-08-13Unify naming of `DocTest`Guillaume Gomez-2/+2
2024-08-13Improve code readabilityGuillaume Gomez-1/+1
2024-08-13Rename `DocTest` into `DocTestBuilder`Guillaume Gomez-1/+1
2024-08-13Correctly handle doctests with invalid ASTGuillaume Gomez-1/+1
2024-08-13Add new doc codeblock `standalone` attributeGuillaume Gomez-0/+6
2024-08-13Split standalone and mergeable doctestsGuillaume Gomez-2/+2
2024-08-13Split doctests between standalone and mergeable onesGuillaume Gomez-2/+2
2024-08-13Add `DocTest` typeGuillaume Gomez-2/+3
2024-08-12Rollup merge of #128394 - GuillaumeGomez:run-button, r=t-rustdocGuillaume Gomez-1/+2
Unify run button display with "copy code" button and with mdbook buttons Follow-up of https://github.com/rust-lang/rust/pull/128339. It looks like this (coherency++, yeay!): ![Screenshot from 2024-07-30 15-16-31](https://github.com/user-attachments/assets/5e262e5b-f338-4085-94ca-e223033a43db) Can be tested [here](https://rustdoc.crud.net/imperio/run-button/foo/struct.Bar.html). r? `@notriddle`
2024-08-08rustdoc: do not run doctests with invalid langstringsMichael Howell-4/+16
2024-08-05Unify run button display with "copy code" button and with mdbook buttonsGuillaume Gomez-1/+2
2024-07-29Reformat `use` declarations.Nicholas Nethercote-14/+13
The previous commit updated `rustfmt.toml` appropriately. This commit is the outcome of running `x fmt --all` with the new formatting options.
2024-06-30rustdoc: update to pulldown-cmark 0.11Michael Howell-57/+54
2024-06-07Move some arguments to fields and reorganize fieldsNoah Lev-2/+10
I moved some local arguments and options to either the local options struct or, if it made sense, the global options struct.
2024-06-07rustdoc: Remove `DoctestVisitor::get_line`Noah Lev-1/+23
This was used to get the line number of the first line from the current docstring, which was then used together with an offset within the docstring. It's simpler to just pass the offset to the visitor and have it do the math because it's clearer and this calculation only needs to be done in one place (the Rust doctest visitor).
2024-06-07rustdoc: Rename `Tester` to `DoctestVisitor`Noah Lev-4/+4
The new name more accurately captures what it is.
2024-06-01Auto merge of #124577 - ↵bors-107/+18
GuillaumeGomez:stabilize-custom_code_classes_in_docs, r=rustdoc Stabilize `custom_code_classes_in_docs` feature Fixes #79483. This feature has been around for quite some time now, I think it's fine to stabilize it now. ## Summary ## 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. EDIT(camelid): This description is out-of-date. Using `custom,class:language-c` will generate the output `<pre class="language-class:language-c">` as would be expected; it treats `class:language-c` as just the name of a language (similar to the langstring `c` or `js` or what have you) since it does not use the designed class syntax. 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)). r? `@notriddle`
2024-05-23Remove `LintDiagnostic::msg`León Orell Valerian Liehr-4/+7
* instead simply set the primary message inside the lint decorator functions * it used to be this way before [#]101986 which introduced `msg` to prevent good path delayed bugs (which no longer exist) from firing under certain circumstances when lints were suppressed / silenced * this is no longer necessary for various reasons I presume * it shaves off complexity and makes further changes easier to implement
2024-05-01Stabilize `custom_code_classes_in_docs` featureGuillaume Gomez-107/+18
2024-04-28Remove direct dependencies on lazy_static, once_cell and byteorderGeorge Bateman-3/+3
The functionality of all three crates is now available in the standard library.
2024-03-05Rename `DiagnosticMessage` as `DiagMessage`.Nicholas Nethercote-4/+4
2024-02-28Rename `DiagnosticBuilder` as `Diag`.Nicholas Nethercote-2/+2
Much better! Note that this involves renaming (and updating the value of) `DIAGNOSTIC_BUILDER` in clippy.
2024-02-15add extra indent spaces for rust-playground linkyukang-2/+5
2024-01-23Rename `TyCtxt::struct_span_lint_hir` as `TyCtxt::node_span_lint`.Nicholas Nethercote-2/+2
2024-01-19Rollup merge of #117662 - GuillaumeGomez:links-in-headings, r=notriddleMatthias Krüger-6/+3
[rustdoc] Allows links in headings Reopening of https://github.com/rust-lang/rust/pull/94360. # Explanations Rustdoc currently doesn't follow the markdown spec on headings: we don't allow links in them. So instead of having headings linking to themselves, this PR generates an anchor on the left side like this: ![image](https://github.com/rust-lang/rust/assets/3050060/a118a7e9-5ef8-4d07-914f-46defc3245c3) <details> <summary>previous version</summary> ![image](https://github.com/rust-lang/rust/assets/3050060/c34fa844-9cd4-47dc-bb51-b37f5f66afee) </details> Having the anchor always displayed allows for mobile devices users to be able to have a link to the anchor. The different color used for the anchor itself is the same as links so people notice when looking at it that they can click on it. You can test it [here](https://rustdoc.crud.net/imperio/links-in-headings/std/index.html). cc `@camelid` r? `@notriddle`
2023-12-15Rollup merge of #119004 - matthiaskrgr:conv, r=compiler-errorsJubilee-1/+1
NFC don't convert types to identical types
2023-12-15NFC don't convert types to identical typesMatthias Krüger-1/+1
2023-12-15Don't pass lint back out of lint decoratorMichael Goulet-6/+4
2023-12-15Rollup merge of #115660 - notriddle:notriddle/sidebar-resize, r=GuillaumeGomezGuillaume Gomez-0/+1
rustdoc: allow resizing the sidebar / hiding the top bar Fixes #97306 Preview: http://notriddle.com/rustdoc-html-demo-4/sidebar-resize/std/index.html ![image](https://github.com/rust-lang/rust/assets/1593513/a2f40ea2-0436-4e44-99e8-d160dab2a680) ## Summary This feature adds: 1. A checkbox to the Settings popover to hide the persistent navigation bar (the sidebar on large viewports and the top bar on small ones). 2. On large viewports, it adds a resize handle to the persistent sidebar. Resizing it into nothing is equivalent to turning off the persistent navigation bar checkbox in Settings. 3. If the navigation bar is hidden, a toolbar button to the left of the search appears. Clicking it brings the navigation bar back. ## Motivation While "mobile mode" is definitely a good default, it's not the only reason people have wanted to hide the sidebar: * Some people use tiling window managers, and don't like rustdoc's current breakpoints. Changing the breakpoints might help with that, but there's no perfect solution, because there's a gap between "huge screen" and "smartphone" where reasonable people can disagree about whether it makes sense for the sidebar to be on-screen. https://github.com/rust-lang/rust/issues/97306 * Some people ask for ways to reduce on-screen clutter because it makes it easier to focus. There's not a media query for that (and if there was, privacy-conscious users would turn it off). https://github.com/rust-lang/rust/issues/59829 This feature is designed to avoid these problems. Resizing the sidebar especially helps, because it provides a way to hide the sidebar without adding a new top-level button (which would add clutter), and it provides a way to make rustdoc play nicer in complex, custom screen layouts. ## Guide and Reference-level explanation On a desktop or laptop with a mouse, resize the sidebar by dragging its right edge. On any browser, including mobile phones, the sticky top bar or side bar can be hidden from the Settings area (the button with the cog wheel, next to the search bar). When it's hidden, a convenient button will appear on the search bar's left. ## Drawbacks This adds more JavaScript code to the render blocking area. ## Rationale and alternatives The most obvious way to allow people to hide the sidebar would have been to let them "manually enter mobile mode." The upside is that it's a feature we already have. The downside is that it's actually really hard to come up with a terse description. Is it: * A Setting that forces desktop viewers to always have the mobile-style top bar? If so, how do we label it? Should it be visible on mobile, and, if so, does it just not do anything? * A persistent hide/show sidebar button, present on desktop, just like on mobile? That's clutter that I'd like to avoid. ## Prior art * The new file browser in GitHub uses a similar divider with a mouse-over indicator * mdBook and macOS Finder both allow you to resize the sidebar to nothing as a gesture to hide it * https://www.nngroup.com/articles/drag-drop/ ## Future possibilities https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/Table.20of.20contents proposes a new, second sidebar (a table of contents). How should it fit in with this feature? Should it be resizeable? Hideable? Can it be accessed on mobile?
2023-12-12Follow guidelines for lint suggestionsGuillaume Gomez-9/+21
2023-12-12Add `rustX` check to codeblock attributes lintGuillaume Gomez-0/+10
2023-12-12Clean up CodeBlocks::next codeGuillaume Gomez-38/+29
2023-12-05Allow links in doc blocks headingsGuillaume Gomez-1/+0
2023-12-05Rework doc blocks headings by not turning them into links anymore and ↵Guillaume Gomez-5/+3
putting an anchor to their left side
2023-11-26rustc: `hir().local_def_id_to_hir_id()` -> `tcx.local_def_id_to_hir_id()` ↵Vadim Petrochenkov-2/+2
cleanup
2023-11-15Re-format code with new rustfmtMark Rousskov-4/+4
2023-11-03clone lessMatthias Krüger-2/+2
2023-10-29feat: Add 'object-safety' ID to init_id_map() in rustdocAlexis (Poliorcetics) Bourget-0/+1
2023-10-11rustdoc: allow resizing the sidebarMichael Howell-0/+1
2023-09-27rustdoc: while -> ifMatthias Krüger-1/+1
we will always return once we step inside the while-loop thus `if` is sufficient here
2023-09-19Allow more characters in custom classesGuillaume Gomez-9/+27
2023-09-18Use old parser if `custom_code_classes_in_docs` feature is not enabledGuillaume Gomez-104/+135
2023-09-17Don't emit an error if the `custom_code_classes_in_docs` feature is disabled ↵Guillaume Gomez-16/+79
when its syntax is used.