Skip to content

Commit 0fc0f21

Browse files
KixironJoshua Nelson
authored andcommitted
Rustdoc
1 parent 754b91d commit 0fc0f21

File tree

5 files changed

+357
-351
lines changed

5 files changed

+357
-351
lines changed

src/web/rustdoc.rs

Lines changed: 53 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,22 @@
11
//! rustdoc handler
22
3-
use super::crate_details::CrateDetails;
4-
use super::error::Nope;
5-
use super::file::File;
6-
use super::metrics;
7-
use super::page::Page;
8-
use super::redirect_base;
9-
use super::{match_version, MatchSemver};
10-
use crate::db::Pool;
11-
use crate::utils;
12-
use crate::Config;
13-
use iron::headers::{CacheControl, CacheDirective, Expires, HttpDate};
14-
use iron::modifiers::Redirect;
15-
use iron::prelude::*;
16-
use iron::Handler;
17-
use iron::{status, Url};
3+
use crate::{
4+
db::Pool,
5+
impl_webpage, utils,
6+
web::{
7+
crate_details::CrateDetails, error::Nope, file::File, match_version, metrics,
8+
page::WebPage, redirect_base, MatchSemver,
9+
},
10+
Config,
11+
};
12+
use iron::{
13+
headers::{CacheControl, CacheDirective, Expires, HttpDate},
14+
modifiers::Redirect,
15+
status, Handler, IronError, IronResult, Plugin, Request, Response, Url,
16+
};
1817
use postgres::Connection;
1918
use router::Router;
20-
use serde::ser::{Serialize, SerializeStruct, Serializer};
21-
22-
#[derive(Debug, Default)]
23-
struct RustdocPage {
24-
head: String,
25-
body: String,
26-
body_class: String,
27-
name: String,
28-
full: String,
29-
version: String,
30-
description: Option<String>,
31-
crate_details: Option<CrateDetails>,
32-
}
33-
34-
impl Serialize for RustdocPage {
35-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36-
where
37-
S: Serializer,
38-
{
39-
let mut state = serializer.serialize_struct("RustdocPage", 9)?;
40-
state.serialize_field("rustdoc_head", &self.head)?;
41-
state.serialize_field("rustdoc_body", &self.body)?;
42-
state.serialize_field("rustdoc_body_class", &self.body_class)?;
43-
state.serialize_field("rustdoc_full", &self.full)?;
44-
state.serialize_field("rustdoc_status", &true)?;
45-
state.serialize_field("name", &self.name)?;
46-
state.serialize_field("version", &self.version)?;
47-
state.serialize_field("description", &self.description)?;
48-
state.serialize_field("crate_details", &self.crate_details)?;
49-
50-
state.end()
51-
}
52-
}
19+
use serde::Serialize;
5320

5421
#[derive(Clone)]
5522
pub struct RustLangRedirector {
@@ -63,6 +30,7 @@ impl RustLangRedirector {
6330
.join(target)
6431
.expect("failed to append crate name to rust-lang.org base URL");
6532
let url = Url::from_generic_url(url).expect("failed to convert url::Url to iron::Url");
33+
6634
Self { url }
6735
}
6836
}
@@ -215,6 +183,22 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {
215183
}
216184
}
217185

186+
#[derive(Debug, Clone, PartialEq, Serialize)]
187+
struct RustdocPage {
188+
latest_path: String,
189+
latest_version: String,
190+
inner_path: String,
191+
is_latest_version: bool,
192+
rustdoc_head: String,
193+
rustdoc_body: String,
194+
rustdoc_body_class: String,
195+
krate: CrateDetails,
196+
}
197+
198+
impl_webpage! {
199+
RustdocPage = "rustdoc/page.html",
200+
}
201+
218202
/// Serves documentation generated by rustdoc.
219203
///
220204
/// This includes all HTML files for an individual crate, as well as the `search-index.js`, which is
@@ -289,11 +273,11 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
289273

290274
// Get the crate's details from the database
291275
// NOTE: we know this crate must exist because we just checked it above (or else `match_version` is buggy)
292-
let crate_details = cexpect!(req, CrateDetails::new(&conn, &name, &version));
276+
let krate = cexpect!(req, CrateDetails::new(&conn, &name, &version));
293277

294278
// if visiting the full path to the default target, remove the target from the path
295279
// expects a req_path that looks like `[/:target]/.*`
296-
if req_path.get(0).copied() == Some(&crate_details.metadata.default_target) {
280+
if req_path.get(0).copied() == Some(&krate.metadata.default_target) {
297281
return redirect(&name, &version, &req_path[1..]);
298282
}
299283

@@ -334,19 +318,20 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
334318

335319
let file_content = ctry!(req, String::from_utf8(file.0.content));
336320
// Extract the head and body of the rustdoc file so that we can insert it into our own html
337-
let (head, body, mut body_class) = ctry!(req, utils::extract_head_and_body(&file_content));
321+
let (rustdoc_head, rustdoc_body, mut rustdoc_body_class) =
322+
ctry!(req, utils::extract_head_and_body(&file_content));
338323

339324
// Add the `rustdoc` classes to the html body
340-
if body_class.is_empty() {
341-
body_class = "rustdoc container-rustdoc".to_string();
325+
if rustdoc_body_class.is_empty() {
326+
rustdoc_body_class = "rustdoc container-rustdoc".to_string();
342327
} else {
343328
// rustdoc adds its own "rustdoc" class to the body
344-
body_class.push_str(" container-rustdoc");
329+
rustdoc_body_class.push_str(" container-rustdoc");
345330
}
346331

347332
rendering_time.step("find latest path");
348333

349-
let latest_release = crate_details.latest_release();
334+
let latest_release = krate.latest_release();
350335

351336
// Get the latest version of the crate
352337
let latest_version = latest_release.version.to_owned();
@@ -366,7 +351,7 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
366351
"/{}/{}/{}",
367352
name,
368353
latest_version,
369-
path_for_version(&latest_path, &crate_details.doc_targets, &conn, &config)
354+
path_for_version(&latest_path, &krate.doc_targets, &conn, &config)
370355
)
371356
} else {
372357
format!("/crate/{}/{}", name, latest_version)
@@ -381,35 +366,25 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {
381366
// Drop the `rustdoc/:crate/:version[/:platform]` prefix
382367
inner_path.drain(..3).for_each(drop);
383368

384-
if inner_path.len() > 1 && crate_details.doc_targets.iter().any(|s| s == inner_path[0]) {
369+
if inner_path.len() > 1 && krate.doc_targets.iter().any(|s| s == inner_path[0]) {
385370
inner_path.remove(0);
386371
}
387372

388373
inner_path.join("/")
389374
};
390375

391376
// Build the page of documentation
392-
let content = RustdocPage {
393-
head,
394-
body,
395-
body_class,
396-
name,
397-
full: file_content,
398-
version,
399-
crate_details: Some(crate_details),
400-
..Default::default()
401-
};
402-
403-
// Build the page served to the user while setting options for templating
404-
Page::new(content)
405-
.set_true("show_package_navigation")
406-
.set_true("package_navigation_documentation_tab")
407-
.set_true("package_navigation_show_platforms_tab")
408-
.set_bool("is_latest_version", is_latest_version)
409-
.set("latest_path", &latest_path)
410-
.set("latest_version", &latest_version)
411-
.set("inner_path", &inner_path)
412-
.to_resp("rustdoc")
377+
RustdocPage {
378+
latest_path,
379+
latest_version,
380+
inner_path,
381+
is_latest_version,
382+
rustdoc_head,
383+
rustdoc_body,
384+
rustdoc_body_class,
385+
krate,
386+
}
387+
.into_response(req)
413388
}
414389

415390
/// Checks whether the given path exists.
@@ -606,12 +581,9 @@ impl Handler for SharedResourceHandler {
606581

607582
#[cfg(test)]
608583
mod test {
609-
use super::*;
610584
use crate::test::*;
611-
use chrono::Utc;
612585
use kuchiki::traits::TendrilSink;
613586
use reqwest::StatusCode;
614-
use serde_json::json;
615587
use std::{collections::BTreeMap, iter::FromIterator};
616588

617589
fn try_latest_version_redirect(
@@ -1455,101 +1427,4 @@ mod test {
14551427
Ok(())
14561428
})
14571429
}
1458-
1459-
#[test]
1460-
fn serialize_rustdoc_page() {
1461-
let time = Utc::now();
1462-
1463-
let details = json!({
1464-
"name": "rcc",
1465-
"version": "100.0.0",
1466-
"description": null,
1467-
"authors": [],
1468-
"owners": [],
1469-
"authors_json": null,
1470-
"dependencies": null,
1471-
"release_time": super::super::duration_to_str(time),
1472-
"build_status": true,
1473-
"last_successful_build": null,
1474-
"rustdoc_status": true,
1475-
"repository_url": null,
1476-
"homepage_url": null,
1477-
"keywords": null,
1478-
"have_examples": true,
1479-
"target_name": "x86_64-unknown-linux-gnu",
1480-
"releases": [],
1481-
"github": true,
1482-
"yanked": false,
1483-
"github_stars": null,
1484-
"github_forks": null,
1485-
"github_issues": null,
1486-
"metadata": {
1487-
"name": "serde",
1488-
"version": "1.0.0",
1489-
"description": "serde does stuff",
1490-
"target_name": null,
1491-
"rustdoc_status": true,
1492-
"default_target": "x86_64-unknown-linux-gnu"
1493-
},
1494-
"is_library": true,
1495-
"doc_targets": [],
1496-
"license": null,
1497-
"documentation_url": null
1498-
});
1499-
1500-
let mut page = RustdocPage {
1501-
head: "<head><title>Whee</title></head>".to_string(),
1502-
body: "<body><h1>idk</h1></body>".to_string(),
1503-
body_class: "docsrs-body".to_string(),
1504-
name: "rcc".to_string(),
1505-
full: "??".to_string(),
1506-
version: "100.0.100".to_string(),
1507-
description: Some("a Rust compiler in C. Wait, maybe the other way around".to_string()),
1508-
crate_details: Some(CrateDetails::default_tester(time)),
1509-
};
1510-
1511-
let correct_json = json!({
1512-
"rustdoc_head": "<head><title>Whee</title></head>",
1513-
"rustdoc_body": "<body><h1>idk</h1></body>",
1514-
"rustdoc_body_class": "docsrs-body",
1515-
"rustdoc_full": "??",
1516-
"rustdoc_status": true,
1517-
"name": "rcc",
1518-
"version": "100.0.100",
1519-
"description": "a Rust compiler in C. Wait, maybe the other way around",
1520-
"crate_details": details
1521-
});
1522-
1523-
assert_eq!(correct_json, serde_json::to_value(&page).unwrap());
1524-
1525-
page.description = None;
1526-
let correct_json = json!({
1527-
"rustdoc_head": "<head><title>Whee</title></head>",
1528-
"rustdoc_body": "<body><h1>idk</h1></body>",
1529-
"rustdoc_body_class": "docsrs-body",
1530-
"rustdoc_full": "??",
1531-
"rustdoc_status": true,
1532-
"name": "rcc",
1533-
"version": "100.0.100",
1534-
"description": null,
1535-
"crate_details": details
1536-
});
1537-
1538-
assert_eq!(correct_json, serde_json::to_value(&page).unwrap());
1539-
1540-
page.crate_details = None;
1541-
let correct_json = json!({
1542-
"rustdoc_head": "<head><title>Whee</title></head>",
1543-
"rustdoc_body": "<body><h1>idk</h1></body>",
1544-
"rustdoc_body_class": "docsrs-body",
1545-
"rustdoc_full": "??",
1546-
"rustdoc_status": true,
1547-
"name": "rcc",
1548-
"version": "100.0.100",
1549-
"description": null,
1550-
"crate_details": null
1551-
});
1552-
1553-
assert_eq!(correct_json, serde_json::to_value(&page).unwrap());
1554-
}
15551430
}

0 commit comments

Comments
 (0)