diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index b99d2fe5aa0d1..011d3cfcf72d7 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -1,6 +1,5 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
-use std::error::Error as StdError;
use std::io;
use std::path::{Path, PathBuf};
use std::rc::Rc;
@@ -16,6 +15,7 @@ use rustc_span::symbol::sym;
use super::cache::{build_index, ExternalLocation};
use super::print_item::{full_path, item_path, print_item};
+use super::templates;
use super::write_shared::write_shared;
use super::{
collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath,
@@ -33,7 +33,6 @@ use crate::formats::FormatRenderer;
use crate::html::escape::Escape;
use crate::html::format::Buffer;
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
-use crate::html::static_files::PAGE;
use crate::html::{layout, sources};
/// Major driving force in all rustdoc rendering. This contains information
@@ -225,7 +224,7 @@ impl<'tcx> Context<'tcx> {
&self.shared.layout,
&page,
|buf: &mut _| print_sidebar(self, it, buf),
- |buf: &mut _| print_item(self, it, buf, &page),
+ |buf: &mut _| print_item(self, &self.shared.templates, it, buf, &page),
&self.shared.style_files,
)
} else {
@@ -416,12 +415,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
};
let mut issue_tracker_base_url = None;
let mut include_sources = true;
-
- let mut templates = tera::Tera::default();
- templates.add_raw_template("page.html", PAGE).map_err(|e| Error {
- file: "page.html".into(),
- error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()),
- })?;
+ let templates = templates::load()?;
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 4f18915974770..dc5aec3b084f5 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -31,6 +31,7 @@ mod tests;
mod context;
mod print_item;
mod span_map;
+mod templates;
mod write_shared;
crate use context::*;
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index cab3fca708b2e..4cfc57ac99588 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -32,16 +32,41 @@ use crate::html::highlight;
use crate::html::layout::Page;
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
+use serde::Serialize;
+
const ITEM_TABLE_OPEN: &'static str = "
";
const ITEM_TABLE_CLOSE: &'static str = "
";
const ITEM_TABLE_ROW_OPEN: &'static str = "";
const ITEM_TABLE_ROW_CLOSE: &'static str = "
";
-pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) {
+// A component in a `use` path, like `string` in std::string::ToString
+#[derive(Serialize)]
+struct PathComponent<'a> {
+ path: String,
+ name: &'a str,
+}
+
+#[derive(Serialize)]
+struct ItemVars<'a> {
+ page: &'a Page<'a>,
+ static_root_path: &'a str,
+ typ: &'a str,
+ name: &'a str,
+ item_type: &'a str,
+ path_components: Vec>,
+ stability_since_raw: &'a str,
+ src_href: Option<&'a str>,
+}
+
+pub(super) fn print_item(
+ cx: &Context<'_>,
+ templates: &tera::Tera,
+ item: &clean::Item,
+ buf: &mut Buffer,
+ page: &Page<'_>,
+) {
debug_assert!(!item.is_stripped());
- // Write the breadcrumb trail header for the top
- buf.write_str("");
- let name = match *item.kind {
+ let typ = match *item.kind {
clean::ModuleItem(_) => {
if item.is_crate() {
"Crate "
@@ -73,48 +98,15 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
unreachable!();
}
};
- buf.write_str(name);
- if !item.is_primitive() && !item.is_keyword() {
- let cur = &cx.current;
- let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() };
- for (i, component) in cur.iter().enumerate().take(amt) {
- write!(
- buf,
- "{}::",
- "../".repeat(cur.len() - i - 1),
- component
- );
- }
- }
- write!(buf, "{}", item.type_(), item.name.as_ref().unwrap());
- write!(
- buf,
- "",
- static_root_path = page.get_static_root_path(),
- suffix = page.resource_suffix,
- );
-
- buf.write_str(""); // in-band
- buf.write_str("");
+ let mut stability_since_raw = Buffer::new();
render_stability_since_raw(
- buf,
+ &mut stability_since_raw,
item.stable_since(cx.tcx()).as_deref(),
item.const_stability(cx.tcx()),
None,
None,
);
- buf.write_str(
- "\
- \
- [−]\
- \
- ",
- );
+ let stability_since_raw: String = stability_since_raw.into_inner();
// Write `src` tag
//
@@ -122,11 +114,38 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
// [src] link in the downstream documentation will actually come back to
// this page, and this link will be auto-clicked. The `id` attribute is
// used to find the link to auto-click.
- if cx.include_sources && !item.is_primitive() {
- write_srclink(cx, item, buf);
- }
+ let src_href =
+ if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
+
+ let path_components = if item.is_primitive() || item.is_keyword() {
+ vec![]
+ } else {
+ let cur = &cx.current;
+ let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() };
+ cur.iter()
+ .enumerate()
+ .take(amt)
+ .map(|(i, component)| PathComponent {
+ path: "../".repeat(cur.len() - i - 1),
+ name: component,
+ })
+ .collect()
+ };
+
+ let item_vars = ItemVars {
+ page: page,
+ static_root_path: page.get_static_root_path(),
+ typ: typ,
+ name: &item.name.as_ref().unwrap().as_str(),
+ item_type: &item.type_().to_string(),
+ path_components: path_components,
+ stability_since_raw: &stability_since_raw,
+ src_href: src_href.as_deref(),
+ };
- buf.write_str("
"); // out-of-band
+ let teractx = tera::Context::from_serialize(item_vars).unwrap();
+ let heading = templates.render("print_item.html", &teractx).unwrap();
+ buf.write_str(&heading);
match *item.kind {
clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
diff --git a/src/librustdoc/html/render/templates.rs b/src/librustdoc/html/render/templates.rs
new file mode 100644
index 0000000000000..d1f182394479a
--- /dev/null
+++ b/src/librustdoc/html/render/templates.rs
@@ -0,0 +1,20 @@
+use std::error::Error as StdError;
+
+use crate::error::Error;
+
+pub(crate) fn load() -> Result {
+ let mut templates = tera::Tera::default();
+
+ macro_rules! include_template {
+ ($file:literal, $fullpath:literal) => {
+ templates.add_raw_template($file, include_str!($fullpath)).map_err(|e| Error {
+ file: $file.into(),
+ error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()),
+ })?
+ };
+ }
+
+ include_template!("page.html", "../templates/page.html");
+ include_template!("print_item.html", "../templates/print_item.html");
+ Ok(templates)
+}
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 6f3d08ea65569..ccc25e6cc495f 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -70,8 +70,6 @@ crate static RUST_FAVICON_SVG: &[u8] = include_bytes!("static/images/favicon.svg
crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/images/favicon-16x16.png");
crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/images/favicon-32x32.png");
-crate static PAGE: &str = include_str!("templates/page.html");
-
/// The built-in themes given to every documentation site.
crate mod themes {
/// The "light" theme, selected by default when no setting is available. Used as the basis for
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
new file mode 100644
index 0000000000000..5a468f3cc1ea0
--- /dev/null
+++ b/src/librustdoc/html/templates/print_item.html
@@ -0,0 +1,26 @@
+ {#- -#}
+ {#- -#}
+ {{-typ-}}
+ {#- The breadcrumbs of the item path, like std::string -#}
+ {%- for component in path_components -%}
+ {{component.name}}::
+ {%- endfor -%}
+ {{name}} {#- -#}
+ {#- -#}
+ {#- -#}
+ {#- -#}
+ {{- stability_since_raw | safe -}}
+ {#- -#}
+ {#- -#}
+ [−] {#- -#}
+ {#- -#}
+ {#- -#}
+ {%- if src_href -%}
+ [src]
+ {%- endif -%}
+ {#- -#}
+
{#- -#}