mirror of
https://github.com/rust-lang/mdBook.git
synced 2025-12-28 20:53:02 -05:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e673c96c2 | ||
|
|
99ecd4f87c | ||
|
|
e839ef0866 | ||
|
|
769cc0a7c1 | ||
|
|
c2686a817a | ||
|
|
bd14d0910a | ||
|
|
6eb597a556 | ||
|
|
59568208ff | ||
|
|
21a16c9b75 | ||
|
|
4e8e1e1408 | ||
|
|
2baed040c2 | ||
|
|
101063093b | ||
|
|
f7ffffbd1e |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## mdBook 0.3.7
|
||||
[88684d8...99ecd4f](https://github.com/rust-lang/mdBook/compare/88684d8...99ecd4f)
|
||||
|
||||
### Changed
|
||||
- Code spans in headers are no longer highlighted as code.
|
||||
[#1162](https://github.com/rust-lang/mdBook/pull/1162)
|
||||
- The sidebar will now scroll the activate page to the middle instead of the top.
|
||||
[#1161](https://github.com/rust-lang/mdBook/pull/1161)
|
||||
- Reverted change to reject build output within the `src` directory, and
|
||||
instead add a check that prevents infinite copies.
|
||||
[#1181](https://github.com/rust-lang/mdBook/pull/1181)
|
||||
[#1026](https://github.com/rust-lang/mdBook/pull/1026)
|
||||
|
||||
### Fixed
|
||||
- Fixed sidebar line-height jumping for collapsed chapters.
|
||||
[#1182](https://github.com/rust-lang/mdBook/pull/1182)
|
||||
- Fixed theme selector focus.
|
||||
[#1170](https://github.com/rust-lang/mdBook/pull/1170)
|
||||
|
||||
## mdBook 0.3.6
|
||||
[efdb832...88684d8](https://github.com/rust-lang/mdBook/compare/efdb832...88684d8)
|
||||
|
||||
|
||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -666,7 +666,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
dependencies = [
|
||||
"ammonia 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mdbook"
|
||||
version = "0.3.6"
|
||||
version = "0.3.7"
|
||||
authors = [
|
||||
"Mathieu David <mathieudavid@mathieudavid.org>",
|
||||
"Michael-F-Bryan <michaelfbryan@gmail.com>",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# mdBook
|
||||
|
||||
[](https://github.com/rust-lang/mdBook/actions?workflow=CI)
|
||||
[](https://github.com/rust-lang/mdBook/actions?workflow=CI)
|
||||
[](https://crates.io/crates/mdbook)
|
||||
[](LICENSE)
|
||||
|
||||
|
||||
@@ -35,5 +35,5 @@ not specified it will default to the value of the `build.build-dir` key in
|
||||
|
||||
-------------------
|
||||
|
||||
***Note:*** *Make sure to run the build command in the root directory and not in
|
||||
the source directory*
|
||||
***Note:*** *The build command copies all files (excluding files with `.md` extension) from the source directory
|
||||
into the build directory.*
|
||||
|
||||
@@ -291,6 +291,7 @@ impl Renderer for HtmlHandlebars {
|
||||
let src_dir = ctx.root.join(&ctx.config.book.src);
|
||||
let destination = &ctx.destination;
|
||||
let book = &ctx.book;
|
||||
let build_dir = ctx.root.join(&ctx.config.build.build_dir);
|
||||
|
||||
if destination.exists() {
|
||||
utils::fs::remove_dir_content(destination)
|
||||
@@ -377,8 +378,8 @@ impl Renderer for HtmlHandlebars {
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all remaining files
|
||||
utils::fs::copy_files_except_ext(&src_dir, &destination, true, &["md"])?;
|
||||
// Copy all remaining files, avoid a recursive copy from/to the book build dir
|
||||
utils::fs::copy_files_except_ext(&src_dir, &destination, true, Some(&build_dir), &["md"])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ fn write_li_open_tag(
|
||||
is_expanded: bool,
|
||||
is_affix: bool,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mut li = String::from("<li class=\"");
|
||||
let mut li = String::from("<li class=\"chapter-item ");
|
||||
if is_expanded {
|
||||
li.push_str("expanded ");
|
||||
}
|
||||
|
||||
@@ -143,6 +143,11 @@ function playpen_text(playpen) {
|
||||
languages: [], // Languages used for auto-detection
|
||||
});
|
||||
|
||||
let code_nodes = Array
|
||||
.from(document.querySelectorAll('code'))
|
||||
// Don't highlight `inline code` blocks in headers.
|
||||
.filter(function (node) {return !node.parentElement.classList.contains("header"); });
|
||||
|
||||
if (window.ace) {
|
||||
// language-rust class needs to be removed for editable
|
||||
// blocks or highlightjs will capture events
|
||||
@@ -154,16 +159,12 @@ function playpen_text(playpen) {
|
||||
.from(document.querySelectorAll('code:not(.editable)'))
|
||||
.forEach(function (block) { hljs.highlightBlock(block); });
|
||||
} else {
|
||||
Array
|
||||
.from(document.querySelectorAll('code'))
|
||||
.forEach(function (block) { hljs.highlightBlock(block); });
|
||||
code_nodes.forEach(function (block) { hljs.highlightBlock(block); });
|
||||
}
|
||||
|
||||
// Adding the hljs class gives code blocks the color css
|
||||
// even if highlighting doesn't apply
|
||||
Array
|
||||
.from(document.querySelectorAll('code'))
|
||||
.forEach(function (block) { block.classList.add('hljs'); });
|
||||
code_nodes.forEach(function (block) { block.classList.add('hljs'); });
|
||||
|
||||
Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {
|
||||
|
||||
@@ -284,7 +285,7 @@ function playpen_text(playpen) {
|
||||
function showThemes() {
|
||||
themePopup.style.display = 'block';
|
||||
themeToggleButton.setAttribute('aria-expanded', true);
|
||||
themePopup.querySelector("button#" + document.body.className).focus();
|
||||
themePopup.querySelector("button#" + get_theme()).focus();
|
||||
}
|
||||
|
||||
function hideThemes() {
|
||||
@@ -293,6 +294,16 @@ function playpen_text(playpen) {
|
||||
themeToggleButton.focus();
|
||||
}
|
||||
|
||||
function get_theme() {
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
|
||||
if (theme === null || theme === undefined) {
|
||||
return default_theme;
|
||||
} else {
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
|
||||
function set_theme(theme, store = true) {
|
||||
let ace_theme;
|
||||
|
||||
@@ -324,9 +335,7 @@ function playpen_text(playpen) {
|
||||
});
|
||||
}
|
||||
|
||||
var previousTheme;
|
||||
try { previousTheme = localStorage.getItem('mdbook-theme'); } catch (e) { }
|
||||
if (previousTheme === null || previousTheme === undefined) { previousTheme = default_theme; }
|
||||
var previousTheme = get_theme();
|
||||
|
||||
if (store) {
|
||||
try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
|
||||
@@ -337,9 +346,7 @@ function playpen_text(playpen) {
|
||||
}
|
||||
|
||||
// Set theme
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
var theme = get_theme();
|
||||
|
||||
set_theme(theme, false);
|
||||
|
||||
@@ -408,7 +415,6 @@ function playpen_text(playpen) {
|
||||
(function sidebar() {
|
||||
var html = document.querySelector("html");
|
||||
var sidebar = document.getElementById("sidebar");
|
||||
var sidebarScrollBox = document.querySelector(".sidebar-scrollbox");
|
||||
var sidebarLinks = document.querySelectorAll('#sidebar a');
|
||||
var sidebarToggleButton = document.getElementById("sidebar-toggle");
|
||||
var sidebarResizeHandle = document.getElementById("sidebar-resize-handle");
|
||||
@@ -507,7 +513,8 @@ function playpen_text(playpen) {
|
||||
// Scroll sidebar to current active section
|
||||
var activeSection = document.getElementById("sidebar").querySelector(".active");
|
||||
if (activeSection) {
|
||||
sidebarScrollBox.scrollTop = activeSection.offsetTop;
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
|
||||
activeSection.scrollIntoView({ block: 'center' });
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -423,7 +423,7 @@ ul#searchresults span.teaser em {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chapter li.expanded {
|
||||
.chapter li.chapter-item {
|
||||
line-height: 1.5em;
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,11 @@ code {
|
||||
font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
|
||||
}
|
||||
|
||||
/* Don't change font size in headers. */
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
font-size: unset;
|
||||
}
|
||||
|
||||
.left { float: left; }
|
||||
.right { float: right; }
|
||||
.boring { opacity: 0.6; }
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div id="sidebar-scrollbox" class="sidebar-scrollbox">
|
||||
<div class="sidebar-scrollbox">
|
||||
{{#toc}}{{/toc}}
|
||||
</div>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||
|
||||
@@ -95,13 +95,15 @@ pub fn copy_files_except_ext(
|
||||
from: &Path,
|
||||
to: &Path,
|
||||
recursive: bool,
|
||||
avoid_dir: Option<&PathBuf>,
|
||||
ext_blacklist: &[&str],
|
||||
) -> Result<()> {
|
||||
debug!(
|
||||
"Copying all files from {} to {} (blacklist: {:?})",
|
||||
"Copying all files from {} to {} (blacklist: {:?}), avoiding {:?}",
|
||||
from.display(),
|
||||
to.display(),
|
||||
ext_blacklist
|
||||
ext_blacklist,
|
||||
avoid_dir
|
||||
);
|
||||
|
||||
// Check that from and to are different
|
||||
@@ -109,15 +111,6 @@ pub fn copy_files_except_ext(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Is the destination inside of the source?
|
||||
if to.canonicalize()?.starts_with(from.canonicalize()?) {
|
||||
return Err(Error::from(format!(
|
||||
"Destination directory cannot be contained in source directory: '{}' is in '{}'",
|
||||
to.display(),
|
||||
from.display()
|
||||
)));
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(from)? {
|
||||
let entry = entry?;
|
||||
let metadata = entry.metadata()?;
|
||||
@@ -128,6 +121,12 @@ pub fn copy_files_except_ext(
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(avoid) = avoid_dir {
|
||||
if entry.path() == *avoid {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check if output dir already exists
|
||||
if !to.join(entry.file_name()).exists() {
|
||||
fs::create_dir(&to.join(entry.file_name()))?;
|
||||
@@ -137,6 +136,7 @@ pub fn copy_files_except_ext(
|
||||
&from.join(entry.file_name()),
|
||||
&to.join(entry.file_name()),
|
||||
true,
|
||||
avoid_dir,
|
||||
ext_blacklist,
|
||||
)?;
|
||||
} else if metadata.is_file() {
|
||||
@@ -185,82 +185,64 @@ mod tests {
|
||||
use super::copy_files_except_ext;
|
||||
use std::fs;
|
||||
|
||||
#[test]
|
||||
fn it_fails_when_destination_is_in_source() {
|
||||
let tmp = match tempfile::TempDir::new() {
|
||||
Ok(t) => t,
|
||||
Err(e) => panic!("Could not create a temp dir: {}", e),
|
||||
};
|
||||
let dst = tmp.path().join("destination");
|
||||
fs::create_dir(&dst).unwrap();
|
||||
assert!(
|
||||
format!("{:?}", copy_files_except_ext(tmp.path(), &dst, true, &[]))
|
||||
.contains("Destination directory cannot be contained in source directory: ")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn copy_files_except_ext_test() {
|
||||
let src = match tempfile::TempDir::new() {
|
||||
let tmp = match tempfile::TempDir::new() {
|
||||
Ok(t) => t,
|
||||
Err(e) => panic!("Could not create a temp dir: {}", e),
|
||||
};
|
||||
|
||||
// Create a couple of files
|
||||
if let Err(err) = fs::File::create(&src.path().join("file.txt")) {
|
||||
if let Err(err) = fs::File::create(&tmp.path().join("file.txt")) {
|
||||
panic!("Could not create file.txt: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::File::create(&src.path().join("file.md")) {
|
||||
if let Err(err) = fs::File::create(&tmp.path().join("file.md")) {
|
||||
panic!("Could not create file.md: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::File::create(&src.path().join("file.png")) {
|
||||
if let Err(err) = fs::File::create(&tmp.path().join("file.png")) {
|
||||
panic!("Could not create file.png: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::create_dir(&src.path().join("sub_dir")) {
|
||||
if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir")) {
|
||||
panic!("Could not create sub_dir: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::File::create(&src.path().join("sub_dir/file.png")) {
|
||||
if let Err(err) = fs::File::create(&tmp.path().join("sub_dir/file.png")) {
|
||||
panic!("Could not create sub_dir/file.png: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::create_dir(&src.path().join("sub_dir_exists")) {
|
||||
if let Err(err) = fs::create_dir(&tmp.path().join("sub_dir_exists")) {
|
||||
panic!("Could not create sub_dir_exists: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::File::create(&src.path().join("sub_dir_exists/file.txt")) {
|
||||
if let Err(err) = fs::File::create(&tmp.path().join("sub_dir_exists/file.txt")) {
|
||||
panic!("Could not create sub_dir_exists/file.txt: {}", err);
|
||||
}
|
||||
|
||||
// Create output dir
|
||||
let dst = match tempfile::TempDir::new() {
|
||||
Ok(t) => t,
|
||||
Err(e) => panic!("Could not create a temp dir: {}", e),
|
||||
};
|
||||
if let Err(err) = fs::create_dir(&dst.path().join("output")) {
|
||||
if let Err(err) = fs::create_dir(&tmp.path().join("output")) {
|
||||
panic!("Could not create output: {}", err);
|
||||
}
|
||||
if let Err(err) = fs::create_dir(&dst.path().join("output/sub_dir_exists")) {
|
||||
if let Err(err) = fs::create_dir(&tmp.path().join("output/sub_dir_exists")) {
|
||||
panic!("Could not create output/sub_dir_exists: {}", err);
|
||||
}
|
||||
|
||||
if let Err(e) =
|
||||
copy_files_except_ext(&src.path(), &dst.path().join("output"), true, &["md"])
|
||||
copy_files_except_ext(&tmp.path(), &tmp.path().join("output"), true, None, &["md"])
|
||||
{
|
||||
panic!("Error while executing the function:\n{:?}", e);
|
||||
}
|
||||
|
||||
// Check if the correct files where created
|
||||
if !(&dst.path().join("output/file.txt")).exists() {
|
||||
if !(&tmp.path().join("output/file.txt")).exists() {
|
||||
panic!("output/file.txt should exist")
|
||||
}
|
||||
if (&dst.path().join("output/file.md")).exists() {
|
||||
if (&tmp.path().join("output/file.md")).exists() {
|
||||
panic!("output/file.md should not exist")
|
||||
}
|
||||
if !(&dst.path().join("output/file.png")).exists() {
|
||||
if !(&tmp.path().join("output/file.png")).exists() {
|
||||
panic!("output/file.png should exist")
|
||||
}
|
||||
if !(&dst.path().join("output/sub_dir/file.png")).exists() {
|
||||
if !(&tmp.path().join("output/sub_dir/file.png")).exists() {
|
||||
panic!("output/sub_dir/file.png should exist")
|
||||
}
|
||||
if !(&dst.path().join("output/sub_dir_exists/file.txt")).exists() {
|
||||
if !(&tmp.path().join("output/sub_dir_exists/file.txt")).exists() {
|
||||
panic!("output/sub_dir/file.png should exist")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user