Skip to content

Commit

Permalink
Auto merge of #55707 - GuillaumeGomez:file-sidebar, r=QuietMisdreavus
Browse files Browse the repository at this point in the history
Add source file sidebar

This is just a start currently but that gives a good overview of what it'll look like:

<img width="1440" alt="screenshot 2018-11-06 at 01 39 15" src="https://user-images.githubusercontent.com/3050060/48035592-05336180-e165-11e8-82e1-5ead0c345eb9.png">

r? @QuietMisdreavus
  • Loading branch information
bors committed Dec 4, 2018
2 parents 91d5d56 + 82a7b6f commit 596e10f
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 63 deletions.
8 changes: 7 additions & 1 deletion src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Page<'a> {

pub fn render<T: fmt::Display, S: fmt::Display>(
dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T,
css_file_extension: bool, themes: &[PathBuf])
css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str])
-> io::Result<()>
{
write!(dst,
Expand Down Expand Up @@ -149,6 +149,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
</script>\
<script src=\"{root_path}aliases.js\"></script>\
<script src=\"{root_path}main{suffix}.js\"></script>\
{extra_scripts}\
<script defer src=\"{root_path}search-index.js\"></script>\
</body>\
</html>",
Expand Down Expand Up @@ -192,6 +193,11 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
page.resource_suffix))
.collect::<String>(),
suffix=page.resource_suffix,
extra_scripts=extra_scripts.iter().map(|e| {
format!("<script src=\"{root_path}{extra_script}.js\"></script>",
root_path=page.root_path,
extra_script=e)
}).collect::<String>(),
)
}

Expand Down
94 changes: 89 additions & 5 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,11 @@ themePicker.onblur = handleThemeButtonsBlur;
write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
static_files::SETTINGS_JS,
options.enable_minification)?;
if cx.shared.include_sources {
write_minify(cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)),
static_files::sidebar::SOURCE_SCRIPT,
options.enable_minification)?;
}

{
let mut data = format!("var resourcesSuffix = \"{}\";\n",
Expand Down Expand Up @@ -969,10 +974,88 @@ themePicker.onblur = handleThemeButtonsBlur;
}
}

use std::ffi::OsString;

#[derive(Debug)]
struct Hierarchy {
elem: OsString,
children: FxHashMap<OsString, Hierarchy>,
elems: FxHashSet<OsString>,
}

impl Hierarchy {
fn new(elem: OsString) -> Hierarchy {
Hierarchy {
elem,
children: FxHashMap::default(),
elems: FxHashSet::default(),
}
}

fn to_json_string(&self) -> String {
let mut subs: Vec<&Hierarchy> = self.children.values().collect();
subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem));
let mut files = self.elems.iter()
.map(|s| format!("\"{}\"",
s.to_str()
.expect("invalid osstring conversion")))
.collect::<Vec<_>>();
files.sort_unstable_by(|a, b| a.cmp(b));
// FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty.
format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}",
name=self.elem.to_str().expect("invalid osstring conversion"),
subs=subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(","),
files=files.join(","))
}
}

if cx.shared.include_sources {
use std::path::Component;

let mut hierarchy = Hierarchy::new(OsString::new());
for source in cx.shared.local_sources.iter()
.filter_map(|p| p.0.strip_prefix(&cx.shared.src_root)
.ok()) {
let mut h = &mut hierarchy;
let mut elems = source.components()
.filter_map(|s| {
match s {
Component::Normal(s) => Some(s.to_owned()),
_ => None,
}
})
.peekable();
loop {
let cur_elem = elems.next().expect("empty file path");
if elems.peek().is_none() {
h.elems.insert(cur_elem);
break;
} else {
let e = cur_elem.clone();
h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e));
h = h.children.get_mut(&cur_elem).expect("not found child");
}
}
}

let dst = cx.dst.join("source-files.js");
let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst);
all_sources.push(format!("sourcesIndex['{}'] = {};",
&krate.name,
hierarchy.to_json_string()));
all_sources.sort();
let mut w = try_err!(File::create(&dst), &dst);
try_err!(writeln!(&mut w,
"var N = null;var sourcesIndex = {{}};\n{}",
all_sources.join("\n")),
&dst);
}

// Update the search index
let dst = cx.dst.join("search-index.js");
let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
all_indexes.push(search_index);

// Sort the indexes by crate so the file will be generated identically even
// with rustdoc running in parallel.
all_indexes.sort();
Expand Down Expand Up @@ -1020,7 +1103,7 @@ themePicker.onblur = handleThemeButtonsBlur;
try_err!(layout::render(&mut w, &cx.shared.layout,
&page, &(""), &content,
cx.shared.css_file_extension.is_some(),
&cx.shared.themes), &dst);
&cx.shared.themes, &[]), &dst);
try_err!(w.flush(), &dst);
}
}
Expand Down Expand Up @@ -1292,7 +1375,8 @@ impl<'a> SourceCollector<'a> {
layout::render(&mut w, &self.scx.layout,
&page, &(""), &Source(contents),
self.scx.css_file_extension.is_some(),
&self.scx.themes)?;
&self.scx.themes, &["source-files",
&format!("source-script{}", page.resource_suffix)])?;
w.flush()?;
self.scx.local_sources.insert(p.clone(), href);
Ok(())
Expand Down Expand Up @@ -1890,7 +1974,7 @@ impl Context {
try_err!(layout::render(&mut w, &self.shared.layout,
&page, &sidebar, &all,
self.shared.css_file_extension.is_some(),
&self.shared.themes),
&self.shared.themes, &[]),
&final_file);

// Generating settings page.
Expand All @@ -1910,7 +1994,7 @@ impl Context {
try_err!(layout::render(&mut w, &layout,
&page, &sidebar, &settings,
self.shared.css_file_extension.is_some(),
&themes),
&themes, &[]),
&settings_file);

Ok(())
Expand Down Expand Up @@ -1968,7 +2052,7 @@ impl Context {
&Sidebar{ cx: self, item: it },
&Item{ cx: self, item: it },
self.shared.css_file_extension.is_some(),
&self.shared.themes)?;
&self.shared.themes, &[])?;
} else {
let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
Expand Down
66 changes: 13 additions & 53 deletions src/librustdoc/html/static/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@
/*jslint browser: true, es5: true */
/*globals $: true, rootPath: true */

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(suffix, length) {
var l = length || this.length;
return this.indexOf(suffix, l - suffix.length) !== -1;
};
}

(function() {
"use strict";

Expand Down Expand Up @@ -57,19 +70,6 @@

var titleBeforeSearch = document.title;

if (!String.prototype.startsWith) {
String.prototype.startsWith = function(searchString, position) {
position = position || 0;
return this.indexOf(searchString, position) === position;
};
}
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(suffix, length) {
var l = length || this.length;
return this.indexOf(suffix, l - suffix.length) !== -1;
};
}

function getPageId() {
var id = document.location.href.split('#')[1];
if (id) {
Expand All @@ -78,46 +78,6 @@
return null;
}

function hasClass(elem, className) {
if (elem && className && elem.className) {
var elemClass = elem.className;
var start = elemClass.indexOf(className);
if (start === -1) {
return false;
} else if (elemClass.length === className.length) {
return true;
} else {
if (start > 0 && elemClass[start - 1] !== ' ') {
return false;
}
var end = start + className.length;
return !(end < elemClass.length && elemClass[end] !== ' ');
}
}
return false;
}

function addClass(elem, className) {
if (elem && className && !hasClass(elem, className)) {
if (elem.className && elem.className.length > 0) {
elem.className += ' ' + className;
} else {
elem.className = className;
}
}
}

function removeClass(elem, className) {
if (elem && className && elem.className) {
elem.className = (" " + elem.className + " ").replace(" " + className + " ", " ")
.trim();
}
}

function isHidden(elem) {
return (elem.offsetParent === null)
}

function showSidebar() {
var elems = document.getElementsByClassName("sidebar-elems")[0];
if (elems) {
Expand Down
74 changes: 70 additions & 4 deletions src/librustdoc/html/static/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ h3.impl, h3.method, h3.type {

h1, h2, h3, h4,
.sidebar, a.source, .search-input, .content table :not(code)>a,
.collapse-toggle, div.item-list .out-of-band {
.collapse-toggle, div.item-list .out-of-band,
#source-sidebar, #sidebar-toggle {
font-family: "Fira Sans", sans-serif;
}

Expand Down Expand Up @@ -668,9 +669,9 @@ a {
padding-right: 10px;
}
.content .search-results td:first-child a:after {
clear: both;
content: "";
display: block;
clear: both;
content: "";
display: block;
}
.content .search-results td:first-child a span {
float: left;
Expand Down Expand Up @@ -1459,3 +1460,68 @@ kbd {
.non-exhaustive {
margin-bottom: 1em;
}

#sidebar-toggle {
position: fixed;
top: 30px;
left: 300px;
z-index: 10;
padding: 3px;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
cursor: pointer;
font-weight: bold;
transition: left .5s;
font-size: 1.2em;
border: 1px solid;
border-left: 0;
}
#source-sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
width: 300px;
z-index: 1;
overflow: auto;
transition: left .5s;
border-right: 1px solid;
}
#source-sidebar > .title {
font-size: 1.5em;
text-align: center;
border-bottom: 1px solid;
margin-bottom: 6px;
}

div.children {
padding-left: 27px;
display: none;
}
div.name {
cursor: pointer;
position: relative;
margin-left: 16px;
}
div.files > a {
display: block;
padding: 0 3px;
}
div.files > a:hover, div.name:hover {
background-color: #a14b4b;
}
div.name.expand + .children {
display: block;
}
div.name::before {
content: "\25B6";
padding-left: 4px;
font-size: 0.7em;
position: absolute;
left: -16px;
top: 4px;
}
div.name.expand::before {
transform: rotate(90deg);
left: -14px;
}
Loading

0 comments on commit 596e10f

Please sign in to comment.