Auto merge of #89695 - jsha:more-templates, r=GuillaumeGomez
Move top part of print_item to Tera templates Part of #84419. This moves the first line of each item page (E.g. `Struct foo::Bar .... 1.0.0 [-][src]` into a Tera template. I also moved template initialization into its own module and added a small macro to reduce duplication and opportunity for errors.
This commit is contained in:
commit
c1cb97481a
6 changed files with 113 additions and 55 deletions
|
@ -1,6 +1,5 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::error::Error as StdError;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -16,6 +15,7 @@ use rustc_span::symbol::sym;
|
||||||
|
|
||||||
use super::cache::{build_index, ExternalLocation};
|
use super::cache::{build_index, ExternalLocation};
|
||||||
use super::print_item::{full_path, item_path, print_item};
|
use super::print_item::{full_path, item_path, print_item};
|
||||||
|
use super::templates;
|
||||||
use super::write_shared::write_shared;
|
use super::write_shared::write_shared;
|
||||||
use super::{
|
use super::{
|
||||||
collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath,
|
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::escape::Escape;
|
||||||
use crate::html::format::Buffer;
|
use crate::html::format::Buffer;
|
||||||
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
||||||
use crate::html::static_files::PAGE;
|
|
||||||
use crate::html::{layout, sources};
|
use crate::html::{layout, sources};
|
||||||
|
|
||||||
/// Major driving force in all rustdoc rendering. This contains information
|
/// Major driving force in all rustdoc rendering. This contains information
|
||||||
|
@ -225,7 +224,7 @@ impl<'tcx> Context<'tcx> {
|
||||||
&self.shared.layout,
|
&self.shared.layout,
|
||||||
&page,
|
&page,
|
||||||
|buf: &mut _| print_sidebar(self, it, buf),
|
|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,
|
&self.shared.style_files,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -416,12 +415,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||||
};
|
};
|
||||||
let mut issue_tracker_base_url = None;
|
let mut issue_tracker_base_url = None;
|
||||||
let mut include_sources = true;
|
let mut include_sources = true;
|
||||||
|
let templates = templates::load()?;
|
||||||
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()),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Crawl the crate attributes looking for attributes which control how we're
|
// Crawl the crate attributes looking for attributes which control how we're
|
||||||
// going to emit HTML
|
// going to emit HTML
|
||||||
|
|
|
@ -31,6 +31,7 @@ mod tests;
|
||||||
mod context;
|
mod context;
|
||||||
mod print_item;
|
mod print_item;
|
||||||
mod span_map;
|
mod span_map;
|
||||||
|
mod templates;
|
||||||
mod write_shared;
|
mod write_shared;
|
||||||
|
|
||||||
crate use context::*;
|
crate use context::*;
|
||||||
|
|
|
@ -32,16 +32,41 @@ use crate::html::highlight;
|
||||||
use crate::html::layout::Page;
|
use crate::html::layout::Page;
|
||||||
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
const ITEM_TABLE_OPEN: &'static str = "<div class=\"item-table\">";
|
const ITEM_TABLE_OPEN: &'static str = "<div class=\"item-table\">";
|
||||||
const ITEM_TABLE_CLOSE: &'static str = "</div>";
|
const ITEM_TABLE_CLOSE: &'static str = "</div>";
|
||||||
const ITEM_TABLE_ROW_OPEN: &'static str = "<div class=\"item-row\">";
|
const ITEM_TABLE_ROW_OPEN: &'static str = "<div class=\"item-row\">";
|
||||||
const ITEM_TABLE_ROW_CLOSE: &'static str = "</div>";
|
const ITEM_TABLE_ROW_CLOSE: &'static str = "</div>";
|
||||||
|
|
||||||
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<PathComponent<'a>>,
|
||||||
|
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());
|
debug_assert!(!item.is_stripped());
|
||||||
// Write the breadcrumb trail header for the top
|
let typ = match *item.kind {
|
||||||
buf.write_str("<h1 class=\"fqn\"><span class=\"in-band\">");
|
|
||||||
let name = match *item.kind {
|
|
||||||
clean::ModuleItem(_) => {
|
clean::ModuleItem(_) => {
|
||||||
if item.is_crate() {
|
if item.is_crate() {
|
||||||
"Crate "
|
"Crate "
|
||||||
|
@ -73,48 +98,15 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
buf.write_str(name);
|
let mut stability_since_raw = Buffer::new();
|
||||||
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,
|
|
||||||
"<a href=\"{}index.html\">{}</a>::<wbr>",
|
|
||||||
"../".repeat(cur.len() - i - 1),
|
|
||||||
component
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
write!(buf, "<a class=\"{}\" href=\"#\">{}</a>", item.type_(), item.name.as_ref().unwrap());
|
|
||||||
write!(
|
|
||||||
buf,
|
|
||||||
"<button id=\"copy-path\" onclick=\"copy_path(this)\" title=\"Copy item path to clipboard\">\
|
|
||||||
<img src=\"{static_root_path}clipboard{suffix}.svg\" \
|
|
||||||
width=\"19\" height=\"18\" \
|
|
||||||
alt=\"Copy item path\">\
|
|
||||||
</button>",
|
|
||||||
static_root_path = page.get_static_root_path(),
|
|
||||||
suffix = page.resource_suffix,
|
|
||||||
);
|
|
||||||
|
|
||||||
buf.write_str("</span>"); // in-band
|
|
||||||
buf.write_str("<span class=\"out-of-band\">");
|
|
||||||
render_stability_since_raw(
|
render_stability_since_raw(
|
||||||
buf,
|
&mut stability_since_raw,
|
||||||
item.stable_since(cx.tcx()).as_deref(),
|
item.stable_since(cx.tcx()).as_deref(),
|
||||||
item.const_stability(cx.tcx()),
|
item.const_stability(cx.tcx()),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
buf.write_str(
|
let stability_since_raw: String = stability_since_raw.into_inner();
|
||||||
"<span id=\"render-detail\">\
|
|
||||||
<a id=\"toggle-all-docs\" href=\"javascript:void(0)\" \
|
|
||||||
title=\"collapse all docs\">\
|
|
||||||
[<span class=\"inner\">−</span>]\
|
|
||||||
</a>\
|
|
||||||
</span>",
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write `src` tag
|
// 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
|
// [src] link in the downstream documentation will actually come back to
|
||||||
// this page, and this link will be auto-clicked. The `id` attribute is
|
// this page, and this link will be auto-clicked. The `id` attribute is
|
||||||
// used to find the link to auto-click.
|
// used to find the link to auto-click.
|
||||||
if cx.include_sources && !item.is_primitive() {
|
let src_href =
|
||||||
write_srclink(cx, item, buf);
|
if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
|
||||||
}
|
|
||||||
|
|
||||||
buf.write_str("</span></h1>"); // out-of-band
|
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(),
|
||||||
|
};
|
||||||
|
|
||||||
|
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 {
|
match *item.kind {
|
||||||
clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
|
clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
|
||||||
|
|
20
src/librustdoc/html/render/templates.rs
Normal file
20
src/librustdoc/html/render/templates.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
|
use crate::error::Error;
|
||||||
|
|
||||||
|
pub(crate) fn load() -> Result<tera::Tera, Error> {
|
||||||
|
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)
|
||||||
|
}
|
|
@ -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_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 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.
|
/// The built-in themes given to every documentation site.
|
||||||
crate mod themes {
|
crate mod themes {
|
||||||
/// The "light" theme, selected by default when no setting is available. Used as the basis for
|
/// The "light" theme, selected by default when no setting is available. Used as the basis for
|
||||||
|
|
26
src/librustdoc/html/templates/print_item.html
Normal file
26
src/librustdoc/html/templates/print_item.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<h1 class="fqn"> {#- -#}
|
||||||
|
<span class="in-band"> {#- -#}
|
||||||
|
{{-typ-}}
|
||||||
|
{#- The breadcrumbs of the item path, like std::string -#}
|
||||||
|
{%- for component in path_components -%}
|
||||||
|
<a href="{{component.path | safe}}index.html">{{component.name}}</a>::<wbr>
|
||||||
|
{%- endfor -%}
|
||||||
|
<a class="{{item_type}}" href="#">{{name}}</a> {#- -#}
|
||||||
|
<button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"> {#- -#}
|
||||||
|
<img src="{{static_root_path | safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
|
||||||
|
width="19" height="18" {# -#}
|
||||||
|
alt="Copy item path"> {#- -#}
|
||||||
|
</button> {#- -#}
|
||||||
|
</span> {#- -#}
|
||||||
|
<span class="out-of-band"> {#- -#}
|
||||||
|
{{- stability_since_raw | safe -}}
|
||||||
|
<span id="render-detail"> {#- -#}
|
||||||
|
<a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs"> {#- -#}
|
||||||
|
[<span class="inner">−</span>] {#- -#}
|
||||||
|
</a> {#- -#}
|
||||||
|
</span> {#- -#}
|
||||||
|
{%- if src_href -%}
|
||||||
|
<a class="srclink" href="{{src_href | safe}}" title="goto source code">[src]</a>
|
||||||
|
{%- endif -%}
|
||||||
|
</span> {#- -#}
|
||||||
|
</h1> {#- -#}
|
Loading…
Add table
Add a link
Reference in a new issue