rustdoc: use more precise URLs for jump-to-definition links

As an example, this cuts down
<https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/mod.rs.html>
by about 11%.

    $ du -h new_mod.rs.html old_mod.rs.html
    296K	new_mod.rs.html
    332K	old_mod.rs.html
This commit is contained in:
Michael Howell 2022-09-15 13:03:04 -07:00
parent 35a0407814
commit ef24747703
3 changed files with 39 additions and 4 deletions

View File

@ -29,6 +29,8 @@ pub(crate) struct HrefContext<'a, 'b, 'c> {
/// This field is used to know "how far" from the top of the directory we are to link to either
/// documentation pages or other source pages.
pub(crate) root_path: &'c str,
/// This field is used to calculate precise local URLs.
pub(crate) current_href: &'c str,
}
/// Decorations are represented as a map from CSS class to vector of character ranges.
@ -977,9 +979,9 @@ fn string_without_closing_tag<T: Display>(
// a link to their definition can be generated using this:
// https://github.com/rust-lang/rust/blob/60f1a2fc4b535ead9c85ce085fdce49b1b097531/src/librustdoc/html/render/context.rs#L315-L338
match href {
LinkFromSrc::Local(span) => context
.href_from_span(*span, true)
.map(|s| format!("{}{}", href_context.root_path, s)),
LinkFromSrc::Local(span) => {
context.href_from_span_relative(*span, href_context.current_href)
}
LinkFromSrc::External(def_id) => {
format::href_with_root_path(*def_id, context, Some(href_context.root_path))
.ok()

View File

@ -31,6 +31,7 @@ use crate::formats::FormatRenderer;
use crate::html::escape::Escape;
use crate::html::format::{join_with_double_colon, Buffer};
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
use crate::html::url_parts_builder::UrlPartsBuilder;
use crate::html::{layout, sources};
use crate::scrape_examples::AllCallLocations;
use crate::try_err;
@ -370,6 +371,35 @@ impl<'tcx> Context<'tcx> {
anchor = anchor
))
}
pub(crate) fn href_from_span_relative(
&self,
span: clean::Span,
relative_to: &str,
) -> Option<String> {
self.href_from_span(span, false).map(|s| {
let mut url = UrlPartsBuilder::new();
let mut dest_href_parts = s.split('/');
let mut cur_href_parts = relative_to.split('/');
for (cur_href_part, dest_href_part) in (&mut cur_href_parts).zip(&mut dest_href_parts) {
if cur_href_part != dest_href_part {
url.push(dest_href_part);
break;
}
}
for dest_href_part in dest_href_parts {
url.push(dest_href_part);
}
let loline = span.lo(self.sess()).line;
let hiline = span.hi(self.sess()).line;
format!(
"{}{}#{}",
"../".repeat(cur_href_parts.count()),
url.finish(),
if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
)
})
}
}
/// Generates the documentation for `crate` into the directory `dst`

View File

@ -288,11 +288,14 @@ pub(crate) fn print_src(
}
}
line_numbers.write_str("</pre>");
let current_href = &context
.href_from_span(clean::Span::new(file_span), false)
.expect("only local crates should have sources emitted");
highlight::render_source_with_highlighting(
s,
buf,
line_numbers,
highlight::HrefContext { context, file_span, root_path },
highlight::HrefContext { context, file_span, root_path, current_href },
decoration_info,
);
}