-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
rustdoc: Migrate sidebar rendering to Askama #108784
Conversation
r? @jsha (rustbot has picked a reviewer for you, use r? to override) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for working on this! This is gonna be awesome. Some early feedback: This moves too much of the logic into the template itself. I would rather see most of the logic continue to be on the Rust side, filling out fields of a Template struct that can then be straightforwardly interpolated into the template using very little flow control and very few method calls. Essentially, the Template struct should be an abstraction layer between "what we want to express" and "what gets rendered as HTML." I think this will have the happy side benefit of making the code easier to understand than it is today, since the Template struct can express intention more clearly without the HTML getting in the way.
As some additional justification for why it's valuable to keep the logic on the Rust side:
- Tooling like jump-to-definition, hover to see types, rustfmt, etc, is not available when viewing an HTML template
- Error messages for mistakes in Rust-inside-HTML-template are harder to understand
- Indentation is hard to manage when going back and forth between HTML code and Rust code within the same HTML template.
I gave an example below of how I think we can add fields to the Sidebar struct such that the HTML template becomes much clearer. I can go through and provide some additional thoughts as I have time, if that would be helpful.
In the STYLE.md doc I tried to express some of these preferences but it's a little easier to see them concretely in action.
{%- if it.is_struct() | ||
|| it.is_trait() | ||
|| it.is_primitive() | ||
|| it.is_union() | ||
|| it.is_enum() | ||
|| it.is_mod() | ||
|| it.is_typedef() -%} | ||
<h2 class="location"><a href="#"> | ||
{%- match it.kind.as_ref() -%} | ||
{%- when clean::ModuleItem with (_) -%} | ||
{%- if it.is_crate() %}Crate{% else %}Module{% endif %} {#+ -#} | ||
{%- else -%} | ||
{%- endmatch -%} | ||
{{- it.name.as_ref().unwrap() -}} | ||
</a></h2>{% endif -%} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would love to see this simplified as:
{%- if !title.is_empty() %-}
<h2 class="location">
<a href="#">{{ title_prefix }}{{ title}}</a>
</h2>
{%- endif -%}
This would necessitate giving Sidebar
a title: &str
and title_prefix: &str
field, and moving the it.is_foo()
logic, plus the "Crate " / "Module " / "" logic back into the Rust code.
{%- if it.is_crate() -%} | ||
<ul class="block"> | ||
{%- match cx.cache().crate_version -%} | ||
{% when Some with (version) %}<li class="version">Version {{version}}</li> | ||
{%- else -%} | ||
{% endmatch -%} | ||
<li><a id="all-types" href="all.html">All Items</a></li>{# -#} | ||
</ul> | ||
{%- endif %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As another example, this could be simplified with the addition of two fields to Sidebar
:
is_crate_page: bool,
crate_version: &'str, // only present on crate pages
Then the template would become:
{%- if is_crate_page -%}
<ul class="block"> {#- -#}
<li class="version">Version {{version}}</li> {#- -#}
<li><a id="all-types" href="all.html">All Items</a></li> {#- -#}
</ul> {#- -#}
{%- endif -%}
By the way, note that I use the double-sided whitespace-eliminating comment {#- -#}
instead of the single-sided on {# -#}
. That allows the comment to stand off from the HTML by a space, which I think is a little more readable.
The single-sided comment {# -#}
is needed when an HTML tag with attributes is spread over multiple lines, in order to preserve one space between attributes. Otherwise the attributes would get jammed together.
This comment has been minimized.
This comment has been minimized.
845cbc0
to
7d0907f
Compare
Hopefully closer to what you're looking for now. I've made a fair amount of use of macros (converted from regular functions in the original code), but it might be simpler/more readable to just inline the loops here. |
@rustbot ready |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Thanks for the revisions.
As you pointed out, it would be nicer to genericize the link blocks and get rid of the macros. I'm thinking something like:
struct<'a> LinkBlock<'a> {
heading: &'a str,
heading_href: &'a str,
links: Vec<Link<'a>>, // Or Iterator?
}
struct<'a> Link<'a> {
href: &'a str,
name: &'a str,
}
And then Sidebar
would have a Vec<LinkBlock>
.
I believe this would allow us to collapse the multiple different .html
files for the different flavors of sidebar, in favor of a single sidebar.html
that iterates across multiple LinkBlocks.
I managed to move it all over to a single |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent, I love the latest refactoring. It adds a lot of clarity to both the template and the code.
Looks like you've got a couple of test cases failing:
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/crate-version-escape" "/checkout/tests/rustdoc/crate-version-escape.rs"
stdout: none
--- stderr -------------------------------
5: @has check failed
`XPATH PATTERN` did not match
// @has 'foo/index.html' '//li[@class="version"]' 'Version <script>alert("hi")</script>'
Encountered 1 errors
------------------------------------------
---- [rustdoc] tests/rustdoc/crate-version.rs stdout ----
error: htmldocck failed!
status: exit status: 1
command: "/usr/bin/python3" "/checkout/src/etc/htmldocck.py" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc/crate-version" "/checkout/tests/rustdoc/crate-version.rs"
stdout: none
--- stderr -------------------------------
3: @has check failed
`XPATH PATTERN` did not match
// @has 'crate_version/index.html' '//*[@class="version"]' 'Version 1.3.37'
Encountered 1 errors
------------------------------------------
failures:
[rustdoc] tests/rustdoc/crate-version-escape.rs
[rustdoc] tests/rustdoc/crate-version.rs
Also one thing I like to do when performing a refactoring like this is generate before-and-after output for ./x.py doc library/std
and diff them; if there are no diffs, the refactoring had no unintended side effects, at least over the std docs.
Interesting, they pass locally. I can see the problem by eye, but odd that it wasn't picked up on my tests.
I've been attempting to do this, but having difficulty since the outputted HTML is all on one line and always seems to have slightly different URLs for resources. Are there any good tools for diffing in this situation? Also looks like there have been some changes to doc layout since the current bootstrap compiler which are getting in the way of diffing 🙁 |
a9c8e07
to
a1e324a
Compare
Ah, upstream changed |
a1e324a
to
aef845e
Compare
Yeah, the all-one-line thing makes it hard. Usually I'll use plain Sometimes I'll do When you say "always seems to have slightly different URLs for resources" - are you talking about the static files in |
The latest test failures seem related to escaping of link fragments in href:
Taking just the fragment, we have (old/new):
It looks like the Note that URL escaping was recently touched in #107284 and #107655. |
aef845e
to
ab4469e
Compare
3b14f00
to
85ae75a
Compare
@bors r+ rollup |
📌 Commit 85ae75aba179e44de205556d7a0acee1e0bd1ef0 has been approved by It is now in the queue for this repository. |
@bors r- Just needs to remove unneeded |
85ae75a
to
2f166d1
Compare
Fixed, and also changed the indentation to be more in line with the style guide |
It looks better indeed. You also removed some unneeded @bors r=jsha,GuillaumeGomez rollup |
…uillaumeGomez rustdoc: Migrate sidebar rendering to Askama cc rust-lang#108757 Renders the sidebar for documentation using an Askama template
…iaskrgr Rollup of 9 pull requests Successful merges: - rust-lang#106276 (Fix `vec_deque::Drain` FIXME) - rust-lang#107629 (rustdoc: sort deprecated items lower in search) - rust-lang#108711 (Add note when matching token with nonterminal) - rust-lang#108757 (rustdoc: Migrate `document_item_info` to Askama) - rust-lang#108784 (rustdoc: Migrate sidebar rendering to Askama) - rust-lang#108927 (Move __thread_local_inner to sys) - rust-lang#108949 (Honor current target when checking conditional compilation values) - rust-lang#108950 (Directly construct Inherited in typeck.) - rust-lang#108988 (rustdoc: Don't crash on `crate` references in blocks) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
cc #108757
Renders the sidebar for documentation using an Askama template