Skip to content

Commit

Permalink
Simplify rendering of stylesheet links into HTML
Browse files Browse the repository at this point in the history
We carry around a list of stylesheets that can carry two different types
of thing:

 1. Internal stylesheets specific to a page type (only for settings)
 2. Themes

In this change I move the link generation for settings.css into
settings(), so Context.style_files is reserved just for themes.

We had two places where we extracted a base theme name from a list of
StylePaths. I consolidated that code to be a method on StylePath.

I moved generation of link tags for stylesheets into the page.html
template. With that change, I made the template responsible for special
handling of light.css (making it the default theme) and of the other
themes (marking them disabled). That allowed getting rid of the
`disabled` field on StylePath.
  • Loading branch information
jsha committed Nov 24, 2021
1 parent ce3f3a5 commit c330963
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ impl Options {
))
.emit();
}
themes.push(StylePath { path: theme_file, disabled: true });
themes.push(StylePath { path: theme_file });
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/librustdoc/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ macro_rules! try_none {
match $e {
Some(e) => e,
None => {
return Err(Error::new(io::Error::new(io::ErrorKind::Other, "not found"), $file));
return Err(<crate::error::Error as crate::docfs::PathError>::new(
io::Error::new(io::ErrorKind::Other, "not found"),
$file,
));
}
}
}};
Expand Down
22 changes: 7 additions & 15 deletions src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::path::PathBuf;

use rustc_data_structures::fx::FxHashMap;

use crate::error::Error;
use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

Expand Down Expand Up @@ -50,7 +50,7 @@ struct PageLayout<'a> {
static_root_path: &'a str,
page: &'a Page<'a>,
layout: &'a Layout,
style_files: String,
themes: Vec<String>,
sidebar: String,
content: String,
krate_with_trailing_slash: String,
Expand All @@ -66,26 +66,18 @@ crate fn render<T: Print, S: Print>(
) -> String {
let static_root_path = page.get_static_root_path();
let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
let style_files = style_files
let themes = style_files
.iter()
.filter_map(|t| t.path.file_stem().map(|stem| (stem, t.disabled)))
.filter_map(|t| t.0.to_str().map(|path| (path, t.1)))
.map(|t| {
format!(
r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
if t.1 { "disabled" } else { "" },
if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
)
})
.collect::<String>();
.map(StylePath::basename)
.collect::<Result<_, Error>>()
.unwrap_or_default();
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 {
static_root_path,
page,
layout,
style_files,
themes,
sidebar,
content,
krate_with_trailing_slash,
Expand Down
18 changes: 11 additions & 7 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// by the browser as the theme stylesheet. The theme system (hackily) works by
// changing the href to this stylesheet. All other themes are disabled to
// prevent rule conflicts
scx.style_files.push(StylePath { path: PathBuf::from("light.css"), disabled: false });
scx.style_files.push(StylePath { path: PathBuf::from("dark.css"), disabled: true });
scx.style_files.push(StylePath { path: PathBuf::from("ayu.css"), disabled: true });
scx.style_files.push(StylePath { path: PathBuf::from("light.css") });
scx.style_files.push(StylePath { path: PathBuf::from("dark.css") });
scx.style_files.push(StylePath { path: PathBuf::from("ayu.css") });

let dst = output;
scx.ensure_dir(&dst)?;
Expand Down Expand Up @@ -596,9 +596,13 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
page.description = "Settings of Rustdoc";
page.root_path = "./";

let mut style_files = self.shared.style_files.clone();
let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
let theme_names: Vec<String> = self
.shared
.style_files
.iter()
.map(StylePath::basename)
.collect::<Result<_, Error>>()?;
let v = layout::render(
&self.shared.templates,
&self.shared.layout,
Expand All @@ -607,9 +611,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
settings(
self.shared.static_root_path.as_deref().unwrap_or("./"),
&self.shared.resource_suffix,
&self.shared.style_files,
theme_names,
)?,
&style_files,
&self.shared.style_files,
);
self.shared.fs.write(settings_file, v)?;
if let Some(ref redirections) = self.shared.redirections {
Expand Down
38 changes: 15 additions & 23 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};

use crate::clean::{self, ItemId, RenderedLink, SelfTy};
use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
Expand Down Expand Up @@ -173,8 +172,12 @@ impl Serialize for TypeWithKind {
crate struct StylePath {
/// The path to the theme
crate path: PathBuf,
/// What the `disabled` attribute should be set to in the HTML tag
crate disabled: bool,
}

impl StylePath {
pub fn basename(&self) -> Result<String, Error> {
Ok(try_none!(try_none!(self.path.file_stem(), &self.path).to_str(), &self.path).to_string())
}
}

fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
Expand Down Expand Up @@ -353,7 +356,7 @@ enum Setting {
js_data_name: &'static str,
description: &'static str,
default_value: &'static str,
options: Vec<(String, String)>,
options: Vec<String>,
},
}

Expand Down Expand Up @@ -393,10 +396,9 @@ impl Setting {
options
.iter()
.map(|opt| format!(
"<option value=\"{}\" {}>{}</option>",
opt.0,
if opt.0 == default_value { "selected" } else { "" },
opt.1,
"<option value=\"{name}\" {}>{name}</option>",
if opt == default_value { "selected" } else { "" },
name = opt,
))
.collect::<String>(),
root_path,
Expand All @@ -421,18 +423,7 @@ impl<T: Into<Setting>> From<(&'static str, Vec<T>)> for Setting {
}
}

fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<String, Error> {
let theme_names: Vec<(String, String)> = themes
.iter()
.map(|entry| {
let theme =
try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path)
.to_string();

Ok((theme.clone(), theme))
})
.collect::<Result<_, Error>>()?;

fn settings(root_path: &str, suffix: &str, theme_names: Vec<String>) -> Result<String, Error> {
// (id, explanation, default value)
let settings: &[Setting] = &[
(
Expand Down Expand Up @@ -469,10 +460,11 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
<span class=\"in-band\">Rustdoc settings</span>\
</h1>\
<div class=\"settings\">{}</div>\
<script src=\"{}settings{}.js\"></script>",
<link rel=\"stylesheet\" href=\"{root_path}settings{suffix}.css\">\
<script src=\"{root_path}settings{suffix}.js\"></script>",
settings.iter().map(|s| s.display(root_path, suffix)).collect::<String>(),
root_path,
suffix
root_path = root_path,
suffix = suffix
))
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/render/write_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,12 @@ pub(super) fn write_shared(
let mut themes: FxHashSet<String> = FxHashSet::default();

for entry in &cx.shared.style_files {
let theme = try_none!(try_none!(entry.path.file_stem(), &entry.path).to_str(), &entry.path);
let theme = entry.basename()?;
let extension =
try_none!(try_none!(entry.path.extension(), &entry.path).to_str(), &entry.path);

// Handle the official themes
match theme {
match theme.as_str() {
"light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
"dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
"ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
Expand Down
10 changes: 9 additions & 1 deletion src/librustdoc/html/templates/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@
<link rel="stylesheet" type="text/css" {# -#}
href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
id="mainThemeStyle"> {#- -#}
{{- style_files | safe -}}
{%- for theme in themes -%}
<link rel="stylesheet" type="text/css" {# -#}
{%- if theme == "light" -%}
id="themeStyle"
{%- else -%}
disabled
{%- endif -%}
href="{{static_root_path | safe}}{{theme}}{{page.resource_suffix}}.css"> {#- -#}
{%- endfor -%}
<script id="default-settings" {# -#}
{% for k, v in layout.default_settings %}
data-{{k}}="{{v}}"
Expand Down

0 comments on commit c330963

Please sign in to comment.