about summary refs log tree commit diff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2020-09-23 22:44:54 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2020-10-28 17:54:06 +0000
commit5cd96d638c37dc7f92cb8b2fc84a3f7bfe7b7960 (patch)
tree63e1a506626c7754d0a9f15b7bcb128f86c05d3e
parent2e10475fdd764365255596e4cb0c21b521456823 (diff)
downloadrust-5cd96d638c37dc7f92cb8b2fc84a3f7bfe7b7960.tar.gz
rust-5cd96d638c37dc7f92cb8b2fc84a3f7bfe7b7960.zip
rustdoc: Provide a way to set the default settings from Rust code
rustdoc has various user-configurable preferences.  These are recorded
in web Local Storage (where available).  But we want to provide a way
to configure the default default, including for when web storage is
not available.

getSettingValue is the function responsible for looking up these
settings.  Here we make it fall back some in-DOM data, which
ultimately comes from RenderOptions.default_settings.

Using HTML data atrtributes is fairly convenient here, dsspite the
need to transform between snake and kebab case to avoid the DOM
converting kebab case to camel case (!)

We cache the element and dataset lookup in a global variable, to
ensure that getSettingValue remains fast.

The DOM representation has to be in an element which precedes the
inclusion of storage.js.  That means it has to be in the <head> and we
should not use an empty <div> as the container (although most browsers
will accept that).  An empty <script> element provides a convenient
and harmless container object.  <meta> would be another possibility
but runs a greater risk of having unwanted behaviours on weird
browsers.

We trust the RenderOptions not to contain unhelpful setting names,
which don't fit nicely into an HTML attribute.  It's awkward to quote
dataset keys.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
-rw-r--r--src/librustdoc/config.rs6
-rw-r--r--src/librustdoc/html/layout.rs8
-rw-r--r--src/librustdoc/html/markdown.rs1
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/static/storage.js24
5 files changed, 39 insertions, 2 deletions
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index a5fc0757816..baa0a934126 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -1,4 +1,4 @@
-use std::collections::BTreeMap;
+use std::collections::{BTreeMap, HashMap};
 use std::convert::TryFrom;
 use std::ffi::OsStr;
 use std::fmt;
@@ -216,6 +216,9 @@ pub struct RenderOptions {
     pub extension_css: Option<PathBuf>,
     /// A map of crate names to the URL to use instead of querying the crate's `html_root_url`.
     pub extern_html_root_urls: BTreeMap<String, String>,
+    /// A map of the default settings (values are as for DOM storage API).  Keys should lack the
+    /// `rustdoc-` prefix.
+    pub default_settings: HashMap<String, String>,
     /// If present, suffix added to CSS/JavaScript files when referencing them in generated pages.
     pub resource_suffix: String,
     /// Whether to run the static CSS/JavaScript through a minifier when outputting them. `true` by
@@ -596,6 +599,7 @@ impl Options {
                 themes,
                 extension_css,
                 extern_html_root_urls,
+                default_settings: Default::default(),
                 resource_suffix,
                 enable_minification,
                 enable_index_page,
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 7239b3c5ba2..54891133662 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
 use std::path::PathBuf;
 
 use crate::externalfiles::ExternalHtml;
@@ -10,6 +11,7 @@ pub struct Layout {
     pub logo: String,
     pub favicon: String,
     pub external_html: ExternalHtml,
+    pub default_settings: HashMap<String, String>,
     pub krate: String,
     /// The given user css file which allow to customize the generated
     /// documentation theme.
@@ -53,6 +55,7 @@ pub fn render<T: Print, S: Print>(
     <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
           id=\"mainThemeStyle\">\
     {style_files}\
+    <script id=\"default-settings\"{default_settings}></script>\
     <script src=\"{static_root_path}storage{suffix}.js\"></script>\
     <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
     {css_extension}\
@@ -172,6 +175,11 @@ pub fn render<T: Print, S: Print>(
         after_content = layout.external_html.after_content,
         sidebar = Buffer::html().to_display(sidebar),
         krate = layout.krate,
+        default_settings = layout
+            .default_settings
+            .iter()
+            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-',"_"), Escape(v),))
+            .collect::<String>(),
         style_files = style_files
             .iter()
             .filter_map(|t| {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 2fd06d7e573..ca8b811681c 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1228,6 +1228,7 @@ fn init_id_map() -> FxHashMap<String, usize> {
     map.insert("render-detail".to_owned(), 1);
     map.insert("toggle-all-docs".to_owned(), 1);
     map.insert("all-types".to_owned(), 1);
+    map.insert("default-settings".to_owned(), 1);
     // This is the list of IDs used by rustdoc sections.
     map.insert("fields".to_owned(), 1);
     map.insert("variants".to_owned(), 1);
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 1726093c6fa..0621eafd913 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -392,6 +392,7 @@ impl FormatRenderer for Context {
             playground_url,
             sort_modules_alphabetically,
             themes: style_files,
+            default_settings,
             extension_css,
             resource_suffix,
             static_root_path,
@@ -415,6 +416,7 @@ impl FormatRenderer for Context {
             logo: String::new(),
             favicon: String::new(),
             external_html,
+            default_settings,
             krate: krate.name.clone(),
             css_file_extension: extension_css,
             generate_search_filter,
diff --git a/src/librustdoc/html/static/storage.js b/src/librustdoc/html/static/storage.js
index 179d7132057..d081781f14b 100644
--- a/src/librustdoc/html/static/storage.js
+++ b/src/librustdoc/html/static/storage.js
@@ -5,8 +5,30 @@ var darkThemes = ["dark", "ayu"];
 var currentTheme = document.getElementById("themeStyle");
 var mainTheme = document.getElementById("mainThemeStyle");
 
+var settingsDataset = (function () {
+    var settingsElement = document.getElementById("default-settings");
+    if (settingsElement === null) {
+        return null;
+    }
+    var dataset = settingsElement.dataset;
+    if (dataset === undefined) {
+        return null;
+    }
+    return dataset;
+})();
+
 function getSettingValue(settingName) {
-    return getCurrentValue('rustdoc-' + settingName);
+    var current = getCurrentValue('rustdoc-' + settingName);
+    if (current !== null) {
+        return current;
+    }
+    if (settingsDataset !== null) {
+        var def = settingsDataset[settingName.replace(/-/g,'_')];
+        if (def !== undefined) {
+            return def;
+        }
+    }
+    return null;
 }
 
 var localStoredTheme = getSettingValue("theme");