Migrate rustdoc from Tera to Askama

See #84419.
This commit is contained in:
Dirkjan Ochtman 2022-01-03 18:18:46 +01:00
parent 89b9f7b284
commit 93a16cb7e2
12 changed files with 130 additions and 135 deletions

View file

@ -103,6 +103,47 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
[[package]]
name = "askama"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d8f355701c672c2ba3d718acbd213f740beea577cc4eae66accdffe15be1882"
dependencies = [
"askama_derive",
"askama_escape",
"askama_shared",
]
[[package]]
name = "askama_derive"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84704cab5b7ae0fd3a9f78ee5eb7b27f3749df445f04623db6633459ae283267"
dependencies = [
"askama_shared",
"proc-macro2",
"syn",
]
[[package]]
name = "askama_escape"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a1bb320f97e6edf9f756bf015900038e43c7700e059688e5724a928c8f3b8d5"
[[package]]
name = "askama_shared"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dae03eebba55a2697a376e58b573a29fe36893157173ac8df312ad85f3c0e012"
dependencies = [
"askama_escape",
"nom",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -1509,17 +1550,6 @@ dependencies = [
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags",
"ignore",
"walkdir",
]
[[package]]
name = "gsgdt"
version = "0.1.2"
@ -2245,6 +2275,12 @@ dependencies = [
"macro-utils",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.4.0"
@ -2304,6 +2340,17 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nom"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
dependencies = [
"memchr",
"minimal-lexical",
"version_check",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -4631,6 +4678,7 @@ name = "rustdoc"
version = "0.0.0"
dependencies = [
"arrayvec",
"askama",
"expect-test",
"itertools 0.9.0",
"minifier",
@ -4642,7 +4690,6 @@ dependencies = [
"serde_json",
"smallvec",
"tempfile",
"tera",
"tracing",
"tracing-subscriber",
"tracing-tree",
@ -5187,21 +5234,6 @@ dependencies = [
"utf-8",
]
[[package]]
name = "tera"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62"
dependencies = [
"globwalk",
"lazy_static",
"pest",
"pest_derive",
"regex",
"serde",
"serde_json",
]
[[package]]
name = "term"
version = "0.6.1"

View file

@ -8,6 +8,7 @@ path = "lib.rs"
[dependencies]
arrayvec = { version = "0.7", default-features = false }
askama = { version = "0.11", default-features = false }
pulldown-cmark = { version = "0.9", default-features = false }
minifier = "0.0.41"
rayon = "1.3.1"
@ -20,7 +21,6 @@ regex = "1"
rustdoc-json-types = { path = "../rustdoc-json-types" }
tracing = "0.1"
tracing-tree = "0.2.0"
tera = { version = "1.10.0", default-features = false }
[dependencies.tracing-subscriber]
version = "0.3.3"

View file

@ -7,6 +7,7 @@
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};
use askama::Template;
use serde::Serialize;
#[derive(Clone, Serialize)]
@ -45,7 +46,8 @@ impl<'a> Page<'a> {
}
}
#[derive(Serialize)]
#[derive(Serialize, Template)]
#[template(path = "page.html")]
struct PageLayout<'a> {
static_root_path: &'a str,
page: &'a Page<'a>,
@ -58,7 +60,6 @@ struct PageLayout<'a> {
}
crate fn render<T: Print, S: Print>(
templates: &tera::Tera,
layout: &Layout,
page: &Page<'_>,
sidebar: S,
@ -76,7 +77,7 @@ struct PageLayout<'a> {
let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
let sidebar = Buffer::html().to_display(sidebar);
let teractx = tera::Context::from_serialize(PageLayout {
PageLayout {
static_root_path,
page,
layout,
@ -85,9 +86,9 @@ struct PageLayout<'a> {
content,
krate_with_trailing_slash,
rustdoc_version,
})
.unwrap();
templates.render("page.html", &teractx).unwrap()
}
.render()
.unwrap()
}
crate fn redirect(url: &str) -> String {

View file

@ -15,7 +15,6 @@
use super::print_item::{full_path, item_path, print_item};
use super::search_index::build_index;
use super::templates;
use super::write_shared::write_shared;
use super::{
collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath,
@ -118,8 +117,6 @@
/// the crate.
redirections: Option<RefCell<FxHashMap<String, String>>>,
pub(crate) templates: tera::Tera,
/// Correspondance map used to link types used in the source code pages to allow to click on
/// links to jump to the type's definition.
crate span_correspondance_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
@ -218,11 +215,10 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String {
if !self.render_redirect_pages {
layout::render(
&self.shared.templates,
&self.shared.layout,
&page,
|buf: &mut _| print_sidebar(self, it, buf),
|buf: &mut _| print_item(self, &self.shared.templates, it, buf, &page),
|buf: &mut _| print_item(self, it, buf, &page),
&self.shared.style_files,
)
} else {
@ -426,7 +422,6 @@ fn init(
};
let mut issue_tracker_base_url = None;
let mut include_sources = true;
let templates = templates::load()?;
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
@ -481,7 +476,6 @@ fn init(
errors: receiver,
redirections: if generate_redirect_map { Some(Default::default()) } else { None },
show_type_layout,
templates,
span_correspondance_map: matches,
cache,
call_locations,
@ -577,7 +571,6 @@ fn after_krate(&mut self) -> Result<(), Error> {
};
let all = self.shared.all.replace(AllTypes::new());
let v = layout::render(
&self.shared.templates,
&self.shared.layout,
&page,
sidebar,
@ -599,7 +592,6 @@ fn after_krate(&mut self) -> Result<(), Error> {
.map(StylePath::basename)
.collect::<Result<_, Error>>()?;
let v = layout::render(
&self.shared.templates,
&self.shared.layout,
&page,
sidebar,

View file

@ -31,7 +31,6 @@
mod context;
mod print_item;
mod span_map;
mod templates;
mod write_shared;
crate use self::context::*;

View file

@ -32,6 +32,7 @@
use crate::html::layout::Page;
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
use askama::Template;
use serde::Serialize;
const ITEM_TABLE_OPEN: &str = "<div class=\"item-table\">";
@ -46,7 +47,8 @@ struct PathComponent<'a> {
name: &'a str,
}
#[derive(Serialize)]
#[derive(Serialize, Template)]
#[template(path = "print_item.html")]
struct ItemVars<'a> {
page: &'a Page<'a>,
static_root_path: &'a str,
@ -58,13 +60,7 @@ struct ItemVars<'a> {
src_href: Option<&'a str>,
}
pub(super) fn print_item(
cx: &Context<'_>,
templates: &tera::Tera,
item: &clean::Item,
buf: &mut Buffer,
page: &Page<'_>,
) {
pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) {
debug_assert!(!item.is_stripped());
let typ = match *item.kind {
clean::ModuleItem(_) => {
@ -143,8 +139,7 @@ pub(super) fn print_item(
src_href: src_href.as_deref(),
};
let teractx = tera::Context::from_serialize(item_vars).unwrap();
let heading = templates.render("print_item.html", &teractx).unwrap();
let heading = item_vars.render().unwrap();
buf.write_str(&heading);
match *item.kind {

View file

@ -1,20 +0,0 @@
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)
}

View file

@ -494,14 +494,7 @@ fn to_json_string(&self) -> String {
})
.collect::<String>()
);
let v = layout::render(
&cx.shared.templates,
&cx.shared.layout,
&page,
"",
content,
&cx.shared.style_files,
);
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
cx.shared.fs.write(dst, v)?;
}
}

View file

@ -203,7 +203,6 @@ fn emit_source(
static_extra_scripts: &[&format!("source-script{}", self.cx.shared.resource_suffix)],
};
let v = layout::render(
&self.cx.shared.templates,
&self.cx.shared.layout,
&page,
"",

View file

@ -7,20 +7,20 @@
<meta name="description" content="{{page.description}}"> {#- -#}
<meta name="keywords" content="{{page.keywords}}"> {#- -#}
<title>{{page.title}}</title> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}FiraSans-Regular.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}FiraSans-Medium.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path | safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Regular.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Regular.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}FiraSans-Medium.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Regular.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceSerif4-Bold.ttf.woff2"> {#- -#}
<link rel="preload" as="font" type="font/woff2" crossorigin href="{{static_root_path|safe}}SourceCodePro-Semibold.ttf.woff2"> {#- -#}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
href="{{static_root_path|safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
href="{{static_root_path|safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
id="mainThemeStyle"> {#- -#}
{%- for theme in themes -%}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
href="{{static_root_path|safe}}{{theme}}{{page.resource_suffix}}.css" {# -#}
{%- if theme == "light" -%}
id="themeStyle"
{%- else -%}
@ -29,41 +29,43 @@
>
{%- endfor -%}
<script id="default-settings" {# -#}
{% for k, v in layout.default_settings %}
{% for (k, v) in layout.default_settings %}
data-{{k}}="{{v}}"
{%- endfor -%}
></script> {#- -#}
<script src="{{static_root_path | safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
<script src="{{page.root_path | safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
<script defer src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
<script src="{{static_root_path|safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
<script src="{{page.root_path|safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
<script defer src="{{static_root_path|safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
{%- for script in page.static_extra_scripts -%}
<script defer src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
<script defer src="{{static_root_path|safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
{%- if layout.scrape_examples_extension -%}
<script defer src="{{page.root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
<script defer src="{{page.root_path|safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
{%- endif -%}
{%- for script in page.extra_scripts -%}
<script defer src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
<script defer src="{{page.root_path|safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
<noscript> {#- -#}
<link rel="stylesheet" {# -#}
href="{{static_root_path | safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
href="{{static_root_path|safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
</noscript> {#- -#}
{%- if layout.css_file_extension -%}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}theme{{page.resource_suffix}}.css"> {#- -#}
{%- endif -%}
{%- if layout.favicon -%}
{%- match layout.css_file_extension -%}
{%- when Some with (ext) -%}
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path|safe}}theme{{page.resource_suffix}}.css"> {#- -#}
{%- else -%}
{%- endmatch -%}
{%- if !layout.favicon.is_empty() -%}
<link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
{%- else -%}
<link rel="alternate icon" type="image/png" {# -#}
href="{{static_root_path | safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
href="{{static_root_path|safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
<link rel="alternate icon" type="image/png" {# -#}
href="{{static_root_path | safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
href="{{static_root_path|safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
<link rel="icon" type="image/svg+xml" {# -#}
href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
href="{{static_root_path|safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
{%- endif -%}
{{- layout.external_html.in_header | safe -}}
{{- layout.external_html.in_header|safe -}}
</head> {#- -#}
<body class="rustdoc {{page.css_class}}"> {#- -#}
<!--[if lte IE 11]> {#- -#}
@ -71,35 +73,35 @@
This old browser is unsupported and will most likely display funky things. {#- -#}
</div> {#- -#}
<![endif]--> {#- -#}
{{- layout.external_html.before_content | safe -}}
{{- layout.external_html.before_content|safe -}}
<nav class="sidebar"> {#- -#}
<div class="sidebar-menu" role="button">&#9776;</div> {#- -#}
<a class="sidebar-logo" href="{{page.root_path | safe}}{{krate_with_trailing_slash | safe}}index.html"> {#- -#}
<a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
<div class="logo-container"> {#- -#}
{%- if layout.logo -%}
<img src="{{layout.logo}}" alt="logo"> {#- -#}
{%- else -%}
<img class="rust-logo" src="{{static_root_path | safe}}rust-logo{{page.resource_suffix}}.png" alt="logo"> {#- -#}
{%- endif -%}
{%- if !layout.logo.is_empty() %}
<img src="{{layout.logo}}" alt="logo"> {#- -#}
{%- else -%}
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.png" alt="logo"> {#- -#}
{%- endif -%}
</div>
</a> {#- -#}
{{- sidebar | safe -}}
{{- sidebar|safe -}}
</nav> {#- -#}
<main> {#- -#}
<div class="width-limiter"> {#- -#}
<div class="sub-container"> {#- -#}
<a class="sub-logo-container" href="{{page.root_path | safe}}{{krate_with_trailing_slash | safe}}index.html"> {#- -#}
{%- if layout.logo -%}
<img src="{{layout.logo}}" alt="logo">
<a class="sub-logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
{%- if !layout.logo.is_empty() %}
<img src="{{layout.logo}}" alt="logo"> {#- -#}
{%- else -%}
<img class="rust-logo" src="{{static_root_path | safe}}rust-logo{{page.resource_suffix}}.png" alt="logo">
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.png" alt="logo"> {#- -#}
{%- endif -%}
</a> {#- -#}
<nav class="sub"> {#- -#}
<div class="theme-picker"> {#- -#}
<button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"> {#- -#}
<img width="18" height="18" alt="Pick another theme!" {# -#}
src="{{static_root_path | safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
src="{{static_root_path|safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
</button> {#- -#}
<div id="theme-choices" role="menu"></div> {#- -#}
</div> {#- -#}
@ -115,23 +117,23 @@
type="search"> {#- -#}
</div> {#- -#}
<button type="button" id="help-button" title="help">?</button> {#- -#}
<a id="settings-menu" href="{{page.root_path | safe}}settings.html" title="settings"> {#- -#}
<a id="settings-menu" href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
<img width="18" height="18" alt="Change settings" {# -#}
src="{{static_root_path | safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
</a> {#- -#}
</div> {#- -#}
</form> {#- -#}
</nav> {#- -#}
</div> {#- -#}
<section id="main-content" class="content">{{- content | safe -}}</section> {#- -#}
<section id="main-content" class="content">{{- content|safe -}}</section> {#- -#}
<section id="search" class="content hidden"></section> {#- -#}
</div> {#- -#}
</main> {#- -#}
{{- layout.external_html.after_content | safe -}}
{{- layout.external_html.after_content|safe -}}
<div id="rustdoc-vars" {# -#}
data-root-path="{{page.root_path | safe}}" {# -#}
data-root-path="{{page.root_path|safe}}" {# -#}
data-current-crate="{{layout.krate}}" {# -#}
data-themes="{{themes | join(sep=",") }}" {# -#}
data-themes="{{themes|join(",") }}" {# -#}
data-resource-suffix="{{page.resource_suffix}}" {# -#}
data-rustdoc-version="{{rustdoc_version}}" {# -#}
> {#- -#}

View file

@ -4,23 +4,25 @@
{{-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>
<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" {# -#}
<img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
width="19" height="18" {# -#}
alt="Copy item path"> {#- -#}
</button> {#- -#}
</span> {#- -#}
</h1> {#- -#}
<span class="out-of-band"> {#- -#}
{% if stability_since_raw %}
{{- stability_since_raw | safe -}} ·
{% if !stability_since_raw.is_empty() %}
{{- stability_since_raw|safe -}} ·
{% endif %}
{%- if src_href %}
<a class="srclink" href="{{src_href | safe}}" title="goto source code">source</a> ·
{% endif -%}
{%- match src_href -%}
{%- when Some with (href) -%}
<a class="srclink" href="{{href|safe}}" title="goto source code">source</a>
{%- else -%} ·
{%- endmatch -%}
<a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs"> {#- -#}
[<span class="inner">&#x2212;</span>] {#- -#}
</a> {#- -#}