1
Fork 0

Migrate top-level rendering to Buffer

This commit is contained in:
Mark Rousskov 2019-08-30 10:24:42 -04:00
parent f35eae9934
commit eebd0265c3
3 changed files with 49 additions and 52 deletions

View file

@ -1,9 +1,9 @@
use std::fmt; use std::fmt;
use std::io;
use std::path::PathBuf; use std::path::PathBuf;
use crate::externalfiles::ExternalHtml; use crate::externalfiles::ExternalHtml;
use crate::html::render::SlashChecker; use crate::html::render::SlashChecker;
use crate::html::format::Buffer;
#[derive(Clone)] #[derive(Clone)]
pub struct Layout { pub struct Layout {
@ -26,7 +26,7 @@ pub struct Page<'a> {
} }
pub fn render<T: fmt::Display, S: fmt::Display>( pub fn render<T: fmt::Display, S: fmt::Display>(
dst: &mut dyn io::Write, dst: &mut Buffer,
layout: &Layout, layout: &Layout,
page: &Page<'_>, page: &Page<'_>,
sidebar: &S, sidebar: &S,
@ -34,7 +34,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
css_file_extension: bool, css_file_extension: bool,
themes: &[PathBuf], themes: &[PathBuf],
generate_search_filter: bool, generate_search_filter: bool,
) -> io::Result<()> { ) {
let static_root_path = page.static_root_path.unwrap_or(page.root_path); let static_root_path = page.static_root_path.unwrap_or(page.root_path);
write!(dst, write!(dst,
"<!DOCTYPE html>\ "<!DOCTYPE html>\
@ -238,7 +238,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
) )
} }
pub fn redirect(dst: &mut dyn io::Write, url: &str) -> io::Result<()> { pub fn redirect(dst: &mut Buffer, url: &str) {
// <script> triggers a redirect before refresh, so this is fine. // <script> triggers a redirect before refresh, so this is fine.
write!(dst, write!(dst,
r##"<!DOCTYPE html> r##"<!DOCTYPE html>

View file

@ -65,7 +65,7 @@ use crate::docfs::{DocFS, ErrorStorage, PathError};
use crate::doctree; use crate::doctree;
use crate::fold::DocFolder; use crate::fold::DocFolder;
use crate::html::escape::Escape; use crate::html::escape::Escape;
use crate::html::format::{AsyncSpace, ConstnessSpace}; use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace};
use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace};
use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace};
use crate::html::format::fmt_impl_for_trait_page; use crate::html::format::fmt_impl_for_trait_page;
@ -1185,13 +1185,13 @@ themePicker.onblur = handleThemeButtonsBlur;
SlashChecker(s), s) SlashChecker(s), s)
}) })
.collect::<String>()); .collect::<String>());
let mut v = Vec::new(); let mut v = Buffer::html();
try_err!(layout::render(&mut v, &cx.shared.layout, layout::render(&mut v, &cx.shared.layout,
&page, &(""), &content, &page, &(""), &content,
cx.shared.css_file_extension.is_some(), cx.shared.css_file_extension.is_some(),
&cx.shared.themes, &cx.shared.themes,
cx.shared.generate_search_filter), &dst); cx.shared.generate_search_filter);
cx.shared.fs.write(&dst, &v)?; cx.shared.fs.write(&dst, v.into_inner().as_bytes())?;
} }
} }
@ -1939,14 +1939,13 @@ impl Context {
} else { } else {
String::new() String::new()
}; };
let mut v = Vec::new(); let mut v = Buffer::html();
try_err!(layout::render(&mut v, &self.shared.layout, layout::render(&mut v, &self.shared.layout,
&page, &sidebar, &all, &page, &sidebar, &all,
self.shared.css_file_extension.is_some(), self.shared.css_file_extension.is_some(),
&self.shared.themes, &self.shared.themes,
self.shared.generate_search_filter), self.shared.generate_search_filter);
&final_file); self.shared.fs.write(&final_file, v.into_inner().as_bytes())?;
self.shared.fs.write(&final_file, &v)?;
// Generating settings page. // Generating settings page.
let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"), let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"),
@ -1959,23 +1958,24 @@ impl Context {
let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>"; let sidebar = "<p class='location'>Settings</p><div class='sidebar-elems'></div>";
themes.push(PathBuf::from("settings.css")); themes.push(PathBuf::from("settings.css"));
let layout = self.shared.layout.clone(); let layout = self.shared.layout.clone();
let mut v = Vec::new(); let mut v = Buffer::html();
try_err!(layout::render(&mut v, &layout, layout::render(
&page, &sidebar, &settings, &mut v,
self.shared.css_file_extension.is_some(), &layout,
&themes, &page, &sidebar, &settings,
self.shared.generate_search_filter), self.shared.css_file_extension.is_some(),
&settings_file); &themes,
self.shared.fs.write(&settings_file, &v)?; self.shared.generate_search_filter,
);
self.shared.fs.write(&settings_file, v.into_inner().as_bytes())?;
Ok(()) Ok(())
} }
fn render_item(&self, fn render_item(&self,
writer: &mut dyn io::Write, writer: &mut Buffer,
it: &clean::Item, it: &clean::Item,
pushname: bool) pushname: bool) {
-> io::Result<()> {
// A little unfortunate that this is done like this, but it sure // A little unfortunate that this is done like this, but it sure
// does make formatting *a lot* nicer. // does make formatting *a lot* nicer.
CURRENT_DEPTH.with(|slot| { CURRENT_DEPTH.with(|slot| {
@ -2027,7 +2027,7 @@ impl Context {
&Item{ cx: self, item: it }, &Item{ cx: self, item: it },
self.shared.css_file_extension.is_some(), self.shared.css_file_extension.is_some(),
&self.shared.themes, &self.shared.themes,
self.shared.generate_search_filter)?; self.shared.generate_search_filter);
} else { } else {
let mut url = self.root_path(); let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
@ -2036,10 +2036,9 @@ impl Context {
url.push_str("/"); url.push_str("/");
} }
url.push_str(&item_path(ty, names.last().unwrap())); url.push_str(&item_path(ty, names.last().unwrap()));
layout::redirect(writer, &url)?; layout::redirect(writer, &url);
} }
} }
Ok(())
} }
/// Non-parallelized version of rendering an item. This will take the input /// Non-parallelized version of rendering an item. This will take the input
@ -2075,13 +2074,13 @@ impl Context {
info!("Recursing into {}", self.dst.display()); info!("Recursing into {}", self.dst.display());
let mut buf = Vec::new(); let mut buf = Buffer::html();
self.render_item(&mut buf, &item, false).unwrap(); self.render_item(&mut buf, &item, false);
// buf will be empty if the module is stripped and there is no redirect for it // buf will be empty if the module is stripped and there is no redirect for it
if !buf.is_empty() { if !buf.is_empty() {
self.shared.ensure_dir(&self.dst)?; self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join("index.html"); let joint_dst = self.dst.join("index.html");
scx.fs.write(&joint_dst, buf)?; scx.fs.write(&joint_dst, buf.into_inner().as_bytes())?;
} }
let m = match item.inner { let m = match item.inner {
@ -2110,8 +2109,8 @@ impl Context {
self.dst = prev; self.dst = prev;
self.current.pop().unwrap(); self.current.pop().unwrap();
} else if item.name.is_some() { } else if item.name.is_some() {
let mut buf = Vec::new(); let mut buf = Buffer::html();
self.render_item(&mut buf, &item, true).unwrap(); self.render_item(&mut buf, &item, true);
// buf will be empty if the item is stripped and there is no redirect for it // buf will be empty if the item is stripped and there is no redirect for it
if !buf.is_empty() { if !buf.is_empty() {
let name = item.name.as_ref().unwrap(); let name = item.name.as_ref().unwrap();
@ -2119,7 +2118,7 @@ impl Context {
let file_name = &item_path(item_type, name); let file_name = &item_path(item_type, name);
self.shared.ensure_dir(&self.dst)?; self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join(file_name); let joint_dst = self.dst.join(file_name);
self.shared.fs.write(&joint_dst, buf)?; self.shared.fs.write(&joint_dst, buf.into_inner().as_bytes())?;
if !self.render_redirect_pages { if !self.render_redirect_pages {
all.append(full_path(self, &item), &item_type); all.append(full_path(self, &item), &item_type);
@ -2129,18 +2128,18 @@ impl Context {
// URL for the page. // URL for the page.
let redir_name = format!("{}.{}.html", name, item_type.name_space()); let redir_name = format!("{}.{}.html", name, item_type.name_space());
let redir_dst = self.dst.join(redir_name); let redir_dst = self.dst.join(redir_name);
let mut v = Vec::new(); let mut v = Buffer::html();
try_err!(layout::redirect(&mut v, file_name), &redir_dst); layout::redirect(&mut v, file_name);
self.shared.fs.write(&redir_dst, &v)?; self.shared.fs.write(&redir_dst, v.into_inner().as_bytes())?;
} }
// If the item is a macro, redirect from the old macro URL (with !) // If the item is a macro, redirect from the old macro URL (with !)
// to the new one (without). // to the new one (without).
if item_type == ItemType::Macro { if item_type == ItemType::Macro {
let redir_name = format!("{}.{}!.html", item_type, name); let redir_name = format!("{}.{}!.html", item_type, name);
let redir_dst = self.dst.join(redir_name); let redir_dst = self.dst.join(redir_name);
let mut v = Vec::new(); let mut v = Buffer::html();
try_err!(layout::redirect(&mut v, file_name), &redir_dst); layout::redirect(&mut v, file_name);
self.shared.fs.write(&redir_dst, &v)?; self.shared.fs.write(&redir_dst, v.into_inner().as_bytes())?;
} }
} }
} }

View file

@ -4,6 +4,7 @@ use crate::fold::DocFolder;
use crate::html::layout; use crate::html::layout;
use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS}; use crate::html::render::{Error, SharedContext, BASIC_KEYWORDS};
use crate::html::highlight; use crate::html::highlight;
use crate::html::format::Buffer;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
@ -105,7 +106,7 @@ impl<'a> SourceCollector<'a> {
cur.push(&fname); cur.push(&fname);
href.push_str(&fname.to_string_lossy()); href.push_str(&fname.to_string_lossy());
let mut v = Vec::new(); let mut v = Buffer::html();
let title = format!("{} -- source", cur.file_name().expect("failed to get file name") let title = format!("{} -- source", cur.file_name().expect("failed to get file name")
.to_string_lossy()); .to_string_lossy());
let desc = format!("Source to the Rust file `{}`.", filename); let desc = format!("Source to the Rust file `{}`.", filename);
@ -120,15 +121,12 @@ impl<'a> SourceCollector<'a> {
extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)], extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)],
static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
}; };
let result = layout::render(&mut v, &self.scx.layout, layout::render(&mut v, &self.scx.layout,
&page, &(""), &Source(contents), &page, &(""), &Source(contents),
self.scx.css_file_extension.is_some(), self.scx.css_file_extension.is_some(),
&self.scx.themes, &self.scx.themes,
self.scx.generate_search_filter); self.scx.generate_search_filter);
if let Err(e) = result { self.scx.fs.write(&cur, v.into_inner().as_bytes())?;
return Err(Error::new(e, &cur));
}
self.scx.fs.write(&cur, &v)?;
self.scx.local_sources.insert(p.clone(), href); self.scx.local_sources.insert(p.clone(), href);
Ok(()) Ok(())
} }