Skip to content

Commit 425aae0

Browse files
Replace tera with askama
1 parent a18e7ec commit 425aae0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+617
-734
lines changed

Cargo.lock

Lines changed: 105 additions & 265 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ tempfile = "3.1.0"
100100
fn-error-context = "0.2.0"
101101

102102
# Templating
103-
tera = { version = "1.5.0", features = ["builtins"] }
103+
# tera = { version = "1.5.0", features = ["builtins"] }
104+
askama = { path = "/home/imperio/rust/askama/askama" } # { git = "https://github.com/djc/askama" }
104105
walkdir = "2"
105106

106107
# Date and Time utilities

src/utils/html.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
use crate::web::page::TemplateData;
1+
use crate::web::page::templates::{Head, Vendored, Body, Topbar};
2+
use crate::web::rustdoc::RustdocPage;
3+
use askama::Template;
24
use lol_html::element;
35
use lol_html::errors::RewritingError;
4-
use tera::Context;
56

67
/// Rewrite a rustdoc page to have the docs.rs topbar
78
///
@@ -12,17 +13,15 @@ use tera::Context;
1213
pub(crate) fn rewrite_lol(
1314
html: &[u8],
1415
max_allowed_memory_usage: usize,
15-
ctx: Context,
16-
templates: &TemplateData,
16+
data: &RustdocPage,
1717
) -> Result<Vec<u8>, RewritingError> {
1818
use lol_html::html_content::{ContentType, Element};
1919
use lol_html::{HtmlRewriter, MemorySettings, Settings};
2020

21-
let templates = &templates.templates;
22-
let tera_head = templates.render("rustdoc/head.html", &ctx).unwrap();
23-
let tera_vendored_css = templates.render("rustdoc/vendored.html", &ctx).unwrap();
24-
let tera_body = templates.render("rustdoc/body.html", &ctx).unwrap();
25-
let tera_rustdoc_topbar = templates.render("rustdoc/topbar.html", &ctx).unwrap();
21+
let head_html = Head::new(data).render().unwrap();
22+
let vendored_html = Vendored::new(data).render().unwrap();
23+
let body_html = Body::new(data).render().unwrap();
24+
let topbar_html = Topbar::new(data).render().unwrap();
2625

2726
// Before: <body> ... rustdoc content ... </body>
2827
// After:
@@ -46,12 +45,12 @@ pub(crate) fn rewrite_lol(
4645
rustdoc_body_class.set_attribute("tabindex", "-1")?;
4746
// Change the `body` to a `div`
4847
rustdoc_body_class.set_tag_name("div")?;
49-
// Prepend the tera content
50-
rustdoc_body_class.prepend(&tera_body, ContentType::Html);
48+
// Prepend the askama content
49+
rustdoc_body_class.prepend(&body_html, ContentType::Html);
5150
// Wrap the transformed body and topbar into a <body> element
5251
rustdoc_body_class.before(r#"<body class="rustdoc-page">"#, ContentType::Html);
5352
// Insert the topbar outside of the rustdoc div
54-
rustdoc_body_class.before(&tera_rustdoc_topbar, ContentType::Html);
53+
rustdoc_body_class.before(&topbar_html, ContentType::Html);
5554
// Finalize body with </body>
5655
rustdoc_body_class.after("</body>", ContentType::Html);
5756

@@ -62,7 +61,7 @@ pub(crate) fn rewrite_lol(
6261
element_content_handlers: vec![
6362
// Append `style.css` stylesheet after all head elements.
6463
element!("head", |head: &mut Element| {
65-
head.append(&tera_head, ContentType::Html);
64+
head.append(&head_html, ContentType::Html);
6665
Ok(())
6766
}),
6867
element!("body", body_handler),
@@ -81,7 +80,7 @@ pub(crate) fn rewrite_lol(
8180
element!(
8281
"link[rel='stylesheet'][href*='rustdoc-']",
8382
|rustdoc_css: &mut Element| {
84-
rustdoc_css.before(&tera_vendored_css, ContentType::Html);
83+
rustdoc_css.before(&vendored_html, ContentType::Html);
8584
Ok(())
8685
}
8786
),

src/web/build_details.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::{
99
AsyncStorage, Config,
1010
};
1111
use anyhow::Context as _;
12+
use askama::Template;
1213
use axum::{
1314
extract::{Extension, Path},
1415
response::IntoResponse,
@@ -27,16 +28,17 @@ pub(crate) struct BuildDetails {
2728
output: String,
2829
}
2930

31+
#[derive(Template)]
32+
#[template(path = "crate/build_details.html")]
3033
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
3134
struct BuildDetailsPage {
3235
metadata: MetaData,
3336
build_details: BuildDetails,
3437
use_direct_platform_links: bool,
38+
csp_nonce: String,
3539
}
3640

37-
impl_axum_webpage! {
38-
BuildDetailsPage = "crate/build_details.html",
39-
}
41+
impl_axum_webpage! { BuildDetailsPage }
4042

4143
pub(crate) async fn build_details_handler(
4244
Path((name, version, id)): Path<(String, String, String)>,
@@ -85,6 +87,7 @@ pub(crate) async fn build_details_handler(
8587
output,
8688
},
8789
use_direct_platform_links: true,
90+
csp_nonce: String::new(),
8891
}
8992
.into_response())
9093
}

src/web/builds.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use axum::{
1616
use chrono::{DateTime, Utc};
1717
use serde::Serialize;
1818
use std::sync::Arc;
19+
use askama::Template;
1920

2021
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
2122
pub(crate) struct Build {
@@ -26,18 +27,19 @@ pub(crate) struct Build {
2627
build_time: DateTime<Utc>,
2728
}
2829

30+
#[derive(Template)]
31+
#[template(path = "crate/builds.html")]
2932
#[derive(Debug, Clone, Serialize)]
3033
struct BuildsPage {
3134
metadata: MetaData,
3235
builds: Vec<Build>,
3336
limits: Limits,
3437
canonical_url: CanonicalUrl,
3538
use_direct_platform_links: bool,
39+
csp_nonce: String,
3640
}
3741

38-
impl_axum_webpage! {
39-
BuildsPage = "crate/builds.html",
40-
}
42+
impl_axum_webpage! { BuildsPage }
4143

4244
pub(crate) async fn build_list_handler(
4345
Path((name, req_version)): Path<(String, String)>,
@@ -68,6 +70,7 @@ pub(crate) async fn build_list_handler(
6870
limits: Limits::for_crate(&config, &mut conn, &name).await?,
6971
canonical_url: CanonicalUrl::from_path(format!("/crate/{name}/latest/builds")),
7072
use_direct_platform_links: true,
73+
csp_nonce: String::new(),
7174
}
7275
.into_response())
7376
}

src/web/crate_details.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{
1515
AsyncStorage,
1616
};
1717
use anyhow::{Context, Result};
18+
use askama::Template;
1819
use axum::{
1920
extract::{Extension, Path},
2021
response::{IntoResponse, Response as AxumResponse},
@@ -365,13 +366,17 @@ pub(crate) fn releases_for_crate(
365366
Ok(releases)
366367
}
367368

369+
370+
#[derive(Template)]
371+
#[template(path = "crate/details.html")]
368372
#[derive(Debug, Clone, PartialEq, Serialize)]
369373
struct CrateDetailsPage {
370374
details: CrateDetails,
375+
csp_nonce: String,
371376
}
372377

373378
impl_axum_webpage! {
374-
CrateDetailsPage = "crate/details.html",
379+
CrateDetailsPage,
375380
cpu_intensive_rendering = true,
376381
}
377382

@@ -440,7 +445,7 @@ pub(crate) async fn crate_details_handler(
440445
Err(e) => warn!("error fetching readme: {:?}", &e),
441446
}
442447

443-
let mut res = CrateDetailsPage { details }.into_response();
448+
let mut res = CrateDetailsPage { details, csp_nonce: String::new() }.into_response();
444449
res.extensions_mut()
445450
.insert::<CachePolicy>(if is_latest_url {
446451
CachePolicy::ForeverInCdn
@@ -450,14 +455,17 @@ pub(crate) async fn crate_details_handler(
450455
Ok(res.into_response())
451456
}
452457

458+
#[derive(Template)]
459+
#[template(path = "rustdoc/releases.html")]
453460
#[derive(Debug, Clone, PartialEq, Serialize)]
454461
struct ReleaseList {
455462
releases: Vec<Release>,
456463
crate_name: String,
464+
csp_nonce: String,
457465
}
458466

459467
impl_axum_webpage! {
460-
ReleaseList = "rustdoc/releases.html",
468+
ReleaseList,
461469
cache_policy = |_| CachePolicy::ForeverInCdn,
462470
cpu_intensive_rendering = true,
463471
}
@@ -494,6 +502,7 @@ pub(crate) async fn get_all_releases(
494502
let res = ReleaseList {
495503
releases,
496504
crate_name: params.name,
505+
csp_nonce: String::new(),
497506
};
498507
Ok(res.into_response())
499508
}
@@ -505,16 +514,19 @@ struct ShortMetadata {
505514
doc_targets: Vec<String>,
506515
}
507516

517+
#[derive(Template)]
518+
#[template(path = "rustdoc/platforms.html")]
508519
#[derive(Debug, Clone, PartialEq, Serialize)]
509520
struct PlatformList {
510521
metadata: ShortMetadata,
511522
inner_path: String,
512523
use_direct_platform_links: bool,
513524
current_target: String,
525+
csp_nonce: String,
514526
}
515527

516528
impl_axum_webpage! {
517-
PlatformList = "rustdoc/platforms.html",
529+
PlatformList,
518530
cache_policy = |_| CachePolicy::ForeverInCdn,
519531
cpu_intensive_rendering = true,
520532
}
@@ -661,6 +673,7 @@ pub(crate) async fn get_all_platforms_inner(
661673
inner_path,
662674
use_direct_platform_links: is_crate_root,
663675
current_target,
676+
csp_nonce: String::new()
664677
};
665678
Ok(res.into_response())
666679
}

src/web/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl IntoResponse for AxumNope {
4242
title: "The requested resource does not exist",
4343
message: "no such resource".into(),
4444
status: StatusCode::NOT_FOUND,
45+
csp_nonce: String::new(),
4546
}
4647
.into_response()
4748
}
@@ -50,6 +51,7 @@ impl IntoResponse for AxumNope {
5051
title: "The requested build does not exist",
5152
message: "no such build".into(),
5253
status: StatusCode::NOT_FOUND,
54+
csp_nonce: String::new(),
5355
}
5456
.into_response(),
5557

@@ -60,6 +62,7 @@ impl IntoResponse for AxumNope {
6062
title: "The requested crate does not exist",
6163
message: "no such crate".into(),
6264
status: StatusCode::NOT_FOUND,
65+
csp_nonce: String::new(),
6366
}
6467
.into_response()
6568
}
@@ -68,6 +71,7 @@ impl IntoResponse for AxumNope {
6871
title: "The requested owner does not exist",
6972
message: "no such owner".into(),
7073
status: StatusCode::NOT_FOUND,
74+
csp_nonce: String::new(),
7175
}
7276
.into_response(),
7377

@@ -78,6 +82,7 @@ impl IntoResponse for AxumNope {
7882
title: "The requested version does not exist",
7983
message: "no such version for this crate".into(),
8084
status: StatusCode::NOT_FOUND,
85+
csp_nonce: String::new(),
8186
}
8287
.into_response()
8388
}
@@ -94,6 +99,7 @@ impl IntoResponse for AxumNope {
9499
title: "Bad request",
95100
message: "Bad request".into(),
96101
status: StatusCode::BAD_REQUEST,
102+
csp_nonce: String::new(),
97103
}
98104
.into_response(),
99105
AxumNope::InternalServerError => {
@@ -102,6 +108,7 @@ impl IntoResponse for AxumNope {
102108
title: "Internal server error",
103109
message: "internal server error".into(),
104110
status: StatusCode::INTERNAL_SERVER_ERROR,
111+
csp_nonce: String::new(),
105112
}
106113
.into_response()
107114
}
@@ -110,6 +117,7 @@ impl IntoResponse for AxumNope {
110117
title: "Internal Server Error",
111118
message: Cow::Owned(source.to_string()),
112119
status: StatusCode::INTERNAL_SERVER_ERROR,
120+
csp_nonce: String::new(),
113121
};
114122

115123
crate::utils::report_error(&source);

src/web/features.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
web::{cache::CachePolicy, error::AxumResult, match_version_axum, MetaData},
88
};
99
use anyhow::anyhow;
10+
use askama::Template;
1011
use axum::{
1112
extract::{Extension, Path},
1213
response::IntoResponse,
@@ -17,6 +18,8 @@ use std::collections::{HashMap, VecDeque};
1718

1819
const DEFAULT_NAME: &str = "default";
1920

21+
#[derive(Template)]
22+
#[template(path = "crate/features.html")]
2023
#[derive(Debug, Clone, Serialize)]
2124
struct FeaturesPage {
2225
metadata: MetaData,
@@ -25,10 +28,11 @@ struct FeaturesPage {
2528
canonical_url: CanonicalUrl,
2629
is_latest_url: bool,
2730
use_direct_platform_links: bool,
31+
csp_nonce: String,
2832
}
2933

3034
impl_axum_webpage! {
31-
FeaturesPage = "crate/features.html",
35+
FeaturesPage,
3236
cache_policy = |page| if page.is_latest_url {
3337
CachePolicy::ForeverInCdn
3438
} else {
@@ -88,6 +92,7 @@ pub(crate) async fn build_features_handler(
8892
is_latest_url,
8993
canonical_url: CanonicalUrl::from_path(format!("/crate/{}/latest/features", &name)),
9094
use_direct_platform_links: true,
95+
csp_nonce: String::new(),
9196
}
9297
.into_response())
9398
}

src/web/highlight.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn with_lang(lang: Option<&str>, code: &str) -> String {
7373
} else {
7474
log::error!("failed while highlighting code: {err:?}");
7575
}
76-
tera::escape_html(code)
76+
crate::web::page::templates::filters::escape_html(code).map(|s| s.to_string()).unwrap_or_default()
7777
}
7878
}
7979
}

src/web/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod page;
55
use crate::utils::get_correct_docsrs_style_file;
66
use crate::utils::{report_error, spawn_blocking};
77
use anyhow::{anyhow, bail, Context as _, Result};
8+
use askama::Template;
89
use axum_extra::middleware::option_layer;
910
use serde_json::Value;
1011
use tracing::{info, instrument};
@@ -24,7 +25,7 @@ mod markdown;
2425
pub(crate) mod metrics;
2526
mod releases;
2627
mod routes;
27-
mod rustdoc;
28+
pub(crate) mod rustdoc;
2829
mod sitemap;
2930
mod source;
3031
mod statics;
@@ -570,6 +571,8 @@ impl MetaData {
570571
}
571572
}
572573

574+
#[derive(Template)]
575+
#[template(path = "error.html")]
573576
#[derive(Debug, Clone, PartialEq, Serialize)]
574577
pub(crate) struct AxumErrorPage {
575578
/// The title of the page
@@ -578,10 +581,11 @@ pub(crate) struct AxumErrorPage {
578581
pub message: Cow<'static, str>,
579582
#[serde(skip)]
580583
pub status: StatusCode,
584+
pub csp_nonce: String,
581585
}
582586

583587
impl_axum_webpage! {
584-
AxumErrorPage = "error.html",
588+
AxumErrorPage,
585589
status = |err| err.status,
586590
}
587591

0 commit comments

Comments
 (0)