Merge remote-tracking branch 'upstream/master' into include-ident

This commit is contained in:
rchaser53 2022-07-01 21:47:56 +09:00
commit 16e38ab0b3
24 changed files with 265 additions and 162 deletions

122
Cargo.lock generated
View File

@ -28,9 +28,9 @@ dependencies = [
[[package]]
name = "ansi_term"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi 0.3.9",
]
@ -228,10 +228,10 @@ dependencies = [
]
[[package]]
name = "difference"
version = "2.0.0"
name = "diff"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
[[package]]
name = "difflib"
@ -283,9 +283,9 @@ dependencies = [
[[package]]
name = "env_logger"
version = "0.7.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
@ -382,25 +382,11 @@ dependencies = [
"new_debug_unreachable",
]
[[package]]
name = "futures"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.16"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
"futures-sink",
@ -408,15 +394,9 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.16"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99"
[[package]]
name = "futures-io"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-macro"
@ -433,9 +413,9 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.16"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
[[package]]
name = "futures-task"
@ -545,7 +525,7 @@ dependencies = [
"log",
"pest",
"pest_derive",
"quick-error 2.0.1",
"quick-error",
"serde",
"serde_json",
]
@ -640,12 +620,9 @@ checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]]
name = "humantime"
version = "1.3.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error 1.2.3",
]
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
@ -712,15 +689,6 @@ dependencies = [
"libc",
]
[[package]]
name = "input_buffer"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413"
dependencies = [
"bytes",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -1232,13 +1200,13 @@ dependencies = [
[[package]]
name = "pretty_assertions"
version = "0.6.1"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563"
dependencies = [
"ansi_term",
"ctor",
"difference",
"diff",
"output_vt100",
]
@ -1274,12 +1242,6 @@ dependencies = [
"unicase",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quick-error"
version = "2.0.1"
@ -1643,6 +1605,26 @@ version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
[[package]]
name = "thiserror"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.43"
@ -1670,11 +1652,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.10.0"
version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b"
checksum = "0c27a64b625de6d309e8c57716ba93021dccf1b3b5c97edd6d3dd2d2135afc0a"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
@ -1687,9 +1668,9 @@ dependencies = [
[[package]]
name = "tokio-macros"
version = "1.3.0"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [
"proc-macro2",
"quote",
@ -1709,9 +1690,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.13.0"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b"
checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8"
dependencies = [
"futures-util",
"log",
@ -1790,19 +1771,19 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tungstenite"
version = "0.12.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24"
checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5"
dependencies = [
"base64",
"byteorder",
"bytes",
"http",
"httparse",
"input_buffer",
"log",
"rand 0.8.4",
"sha-1 0.9.7",
"thiserror",
"url",
"utf-8",
]
@ -1905,12 +1886,13 @@ dependencies = [
[[package]]
name = "warp"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054"
checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e"
dependencies = [
"bytes",
"futures",
"futures-channel",
"futures-util",
"headers",
"http",
"hyper",

View File

@ -20,7 +20,7 @@ anyhow = "1.0.28"
chrono = "0.4"
clap = { version = "3.0", features = ["cargo"] }
clap_complete = "3.0"
env_logger = "0.7.1"
env_logger = "0.9.0"
handlebars = "4.0"
lazy_static = "1.0"
log = "0.4"
@ -42,7 +42,7 @@ gitignore = { version = "1.0", optional = true }
# Serve feature
futures-util = { version = "0.3.4", optional = true }
tokio = { version = "1", features = ["macros", "rt-multi-thread"], optional = true }
warp = { version = "0.3.1", default-features = false, features = ["websocket"], optional = true }
warp = { version = "0.3.2", default-features = false, features = ["websocket"], optional = true }
# Search feature
elasticlunr-rs = { version = "3.0.0", optional = true }
@ -53,7 +53,7 @@ assert_cmd = "1"
predicates = "2"
select = "0.5"
semver = "1.0"
pretty_assertions = "0.6"
pretty_assertions = "1.2.1"
walkdir = "2.0"
[features]

View File

@ -30,6 +30,8 @@ cargo install mdbook
This will automatically download mdBook from [crates.io], build it, and install it in Cargo's global binary directory (`~/.cargo/bin/` by default).
To uninstall, run the command `cargo uninstall mdbook`.
[Rust installation page]: https://www.rust-lang.org/tools/install
[crates.io]: https://crates.io/

View File

@ -386,7 +386,7 @@ fn determine_renderers(config: &Config) -> Vec<Box<dyn Renderer>> {
renderers
}
const DEFAULT_PREPROCESSORS: &[&'static str] = &["links", "index"];
const DEFAULT_PREPROCESSORS: &[&str] = &["links", "index"];
fn is_default_preprocessor(pre: &dyn Preprocessor) -> bool {
let name = pre.name();
@ -756,10 +756,9 @@ mod tests {
let preprocessors = determine_preprocessors(&cfg).unwrap();
assert!(preprocessors
assert!(!preprocessors
.iter()
.find(|preprocessor| preprocessor.name() == "random")
.is_none());
.any(|preprocessor| preprocessor.name() == "random"));
}
#[test]
@ -776,10 +775,9 @@ mod tests {
let preprocessors = determine_preprocessors(&cfg).unwrap();
assert!(preprocessors
assert!(!preprocessors
.iter()
.find(|preprocessor| preprocessor.name() == "links")
.is_none());
.any(|preprocessor| preprocessor.name() == "links"));
}
#[test]

View File

@ -122,8 +122,5 @@ fn confirm() -> bool {
io::stdout().flush().unwrap();
let mut s = String::new();
io::stdin().read_line(&mut s).ok();
match &*s.trim() {
"Y" | "y" | "yes" | "Yes" => true,
_ => false,
}
matches!(&*s.trim(), "Y" | "y" | "yes" | "Yes")
}

View File

@ -227,10 +227,10 @@ impl Config {
let value = Value::try_from(value)
.with_context(|| "Unable to represent the item as a JSON Value")?;
if index.starts_with("book.") {
self.book.update_value(&index[5..], value);
} else if index.starts_with("build.") {
self.build.update_value(&index[6..], value);
if let Some(key) = index.strip_prefix("book.") {
self.book.update_value(key, value);
} else if let Some(key) = index.strip_prefix("build.") {
self.build.update_value(key, value);
} else {
self.rest.insert(index, value);
}
@ -371,15 +371,8 @@ impl Serialize for Config {
}
fn parse_env(key: &str) -> Option<String> {
const PREFIX: &str = "MDBOOK_";
if key.starts_with(PREFIX) {
let key = &key[PREFIX.len()..];
Some(key.to_lowercase().replace("__", ".").replace("_", "-"))
} else {
None
}
key.strip_prefix("MDBOOK_")
.map(|key| key.to_lowercase().replace("__", ".").replace('_', "-"))
}
fn is_legacy_format(table: &Value) -> bool {
@ -828,7 +821,7 @@ mod tests {
"#;
let got = Config::from_str(src).unwrap();
assert_eq!(got.html_config().unwrap().playground.runnable, false);
assert!(!got.html_config().unwrap().playground.runnable);
}
#[test]
@ -1037,7 +1030,7 @@ mod tests {
fn encode_env_var(key: &str) -> String {
format!(
"MDBOOK_{}",
key.to_uppercase().replace('.', "__").replace("-", "_")
key.to_uppercase().replace('.', "__").replace('-', "_")
)
}
@ -1061,11 +1054,10 @@ mod tests {
}
#[test]
#[allow(clippy::approx_constant)]
fn update_config_using_env_var_and_complex_value() {
let mut cfg = Config::default();
let key = "foo-bar.baz";
let value = json!({"array": [1, 2, 3], "number": 3.14});
let value = json!({"array": [1, 2, 3], "number": 13.37});
let value_str = serde_json::to_string(&value).unwrap();
assert!(cfg.get(key).is_none());
@ -1184,15 +1176,15 @@ mod tests {
"#;
let got = Config::from_str(src).unwrap();
let html_config = got.html_config().unwrap();
assert_eq!(html_config.print.enable, false);
assert_eq!(html_config.print.page_break, true);
assert!(!html_config.print.enable);
assert!(html_config.print.page_break);
let src = r#"
[output.html.print]
page-break = false
"#;
let got = Config::from_str(src).unwrap();
let html_config = got.html_config().unwrap();
assert_eq!(html_config.print.enable, true);
assert_eq!(html_config.print.page_break, false);
assert!(html_config.print.enable);
assert!(!html_config.print.page_break);
}
}

View File

@ -82,7 +82,6 @@
#![deny(missing_docs)]
#![deny(rust_2018_idioms)]
#![allow(clippy::comparison_chain)]
#[macro_use]
extern crate lazy_static;

View File

@ -153,6 +153,7 @@ enum RangeOrAnchor {
}
// A range of lines specified with some include directive.
#[allow(clippy::enum_variant_names)] // The prefix can't be removed, and is meant to mirror the contained type
#[derive(PartialEq, Debug, Clone)]
enum LineRange {
Range(Range<usize>),

View File

@ -116,7 +116,7 @@ impl HtmlHandlebars {
if ctx.is_index {
ctx.data.insert("path".to_owned(), json!("index.md"));
ctx.data.insert("path_to_root".to_owned(), json!(""));
ctx.data.insert("is_index".to_owned(), json!("true"));
ctx.data.insert("is_index".to_owned(), json!(true));
let rendered_index = ctx.handlebars.render("index", &ctx.data)?;
let rendered_index =
self.post_process(rendered_index, &ctx.html_config.playground, ctx.edition);
@ -540,7 +540,8 @@ impl Renderer for HtmlHandlebars {
chapter_titles: &ctx.chapter_titles,
};
self.render_item(item, ctx, &mut print_content)?;
is_index = false;
// Only the first non-draft chapter item should be treated as the "index"
is_index &= !matches!(item, BookItem::Chapter(ch) if !ch.is_draft_chapter());
}
// Render 404 page
@ -814,7 +815,7 @@ fn fix_code_blocks(html: &str) -> String {
FIX_CODE_BLOCKS
.replace_all(html, |caps: &Captures<'_>| {
let before = &caps[1];
let classes = &caps[2].replace(",", " ");
let classes = &caps[2].replace(',', " ");
let after = &caps[3];
format!(
@ -880,11 +881,8 @@ fn add_playground_pre(
// we need to inject our own main
let (attrs, code) = partition_source(code);
format!(
"\n# #![allow(unused)]\n{}#fn main() {{\n{}#}}",
attrs, code
)
.into()
format!("# #![allow(unused)]\n{}#fn main() {{\n{}#}}", attrs, code)
.into()
};
hide_lines(&content)
}
@ -1007,7 +1005,7 @@ mod tests {
fn add_playground() {
let inputs = [
("<code class=\"language-rust\">x()</code>",
"<pre class=\"playground\"><code class=\"language-rust\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
"<pre class=\"playground\"><code class=\"language-rust\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playground\"><code class=\"language-rust\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust editable\">let s = \"foo\n # bar\n\";</code>",
@ -1037,7 +1035,7 @@ mod tests {
fn add_playground_edition2015() {
let inputs = [
("<code class=\"language-rust\">x()</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2015\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
"<pre class=\"playground\"><code class=\"language-rust edition2015\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2015\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2015\">fn main() {}</code>",
@ -1061,7 +1059,7 @@ mod tests {
fn add_playground_edition2018() {
let inputs = [
("<code class=\"language-rust\">x()</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2018\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
"<pre class=\"playground\"><code class=\"language-rust edition2018\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2018\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2015\">fn main() {}</code>",
@ -1085,7 +1083,7 @@ mod tests {
fn add_playground_edition2021() {
let inputs = [
("<code class=\"language-rust\">x()</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2021\">\n<span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
"<pre class=\"playground\"><code class=\"language-rust edition2021\"><span class=\"boring\">#![allow(unused)]\n</span><span class=\"boring\">fn main() {\n</span>x()\n<span class=\"boring\">}\n</span></code></pre>"),
("<code class=\"language-rust\">fn main() {}</code>",
"<pre class=\"playground\"><code class=\"language-rust edition2021\">fn main() {}\n</code></pre>"),
("<code class=\"language-rust edition2015\">fn main() {}</code>",

View File

@ -61,7 +61,7 @@ fn find_chapter(
.as_json()
.as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
.replace("\"", "");
.replace('\"', "");
if !rc.evaluate(ctx, "@root/is_index")?.is_missing() {
// Special case for index.md which may be a synthetic page.
@ -121,7 +121,7 @@ fn render(
.as_json()
.as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
.replace("\"", "");
.replace('\"', "");
context.insert(
"path_to_root".to_owned(),
@ -141,7 +141,7 @@ fn render(
.with_extension("html")
.to_str()
.ok_or_else(|| RenderError::new("Link could not be converted to str"))
.map(|p| context.insert("link".to_owned(), json!(p.replace("\\", "/"))))
.map(|p| context.insert("link".to_owned(), json!(p.replace('\\', "/"))))
})?;
trace!("Render template");

View File

@ -1,5 +1,5 @@
use std::collections::BTreeMap;
use std::path::Path;
use std::{cmp::Ordering, collections::BTreeMap};
use crate::utils;
use crate::utils::bracket_escape;
@ -33,7 +33,7 @@ impl HelperDef for RenderToc {
.as_json()
.as_str()
.ok_or_else(|| RenderError::new("Type error for `path`, string expected"))?
.replace("\"", "");
.replace('\"', "");
let current_section = rc
.evaluate(ctx, "@root/section")?
@ -57,6 +57,11 @@ impl HelperDef for RenderToc {
out.write("<ol class=\"chapter\">")?;
let mut current_level = 1;
// The "index" page, which has this attribute set, is supposed to alias the first chapter in
// the book, i.e. the first link. There seems to be no easy way to determine which chapter
// the "index" is aliasing from within the renderer, so this is used instead to force the
// first link to be active. See further below.
let mut is_first_chapter = ctx.data().get("is_index").is_some();
for item in chapters {
// Spacer
@ -81,22 +86,26 @@ impl HelperDef for RenderToc {
level - 1 < fold_level as usize
};
if level > current_level {
while level > current_level {
out.write("<li>")?;
out.write("<ol class=\"section\">")?;
current_level += 1;
match level.cmp(&current_level) {
Ordering::Greater => {
while level > current_level {
out.write("<li>")?;
out.write("<ol class=\"section\">")?;
current_level += 1;
}
write_li_open_tag(out, is_expanded, false)?;
}
write_li_open_tag(out, is_expanded, false)?;
} else if level < current_level {
while level < current_level {
out.write("</ol>")?;
out.write("</li>")?;
current_level -= 1;
Ordering::Less => {
while level < current_level {
out.write("</ol>")?;
out.write("</li>")?;
current_level -= 1;
}
write_li_open_tag(out, is_expanded, false)?;
}
Ordering::Equal => {
write_li_open_tag(out, is_expanded, item.get("section").is_none())?;
}
write_li_open_tag(out, is_expanded, false)?;
} else {
write_li_open_tag(out, is_expanded, item.get("section").is_none())?;
}
// Part title
@ -119,14 +128,15 @@ impl HelperDef for RenderToc {
.to_str()
.unwrap()
// Hack for windows who tends to use `\` as separator instead of `/`
.replace("\\", "/");
.replace('\\', "/");
// Add link
out.write(&utils::fs::path_to_root(&current_path))?;
out.write(&tmp)?;
out.write("\"")?;
if path == &current_path {
if path == &current_path || is_first_chapter {
is_first_chapter = false;
out.write(" class=\"active\"")?;
}

View File

@ -2,7 +2,7 @@ use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::path::Path;
use elasticlunr::Index;
use elasticlunr::{Index, IndexBuilder};
use pulldown_cmark::*;
use crate::book::{Book, BookItem};
@ -13,9 +13,25 @@ use crate::utils;
use serde::Serialize;
const MAX_WORD_LENGTH_TO_INDEX: usize = 80;
/// Tokenizes in the same way as elasticlunr-rs (for English), but also drops long tokens.
fn tokenize(text: &str) -> Vec<String> {
text.split(|c: char| c.is_whitespace() || c == '-')
.filter(|s| !s.is_empty())
.map(|s| s.trim().to_lowercase())
.filter(|s| s.len() <= MAX_WORD_LENGTH_TO_INDEX)
.collect()
}
/// Creates all files required for search.
pub fn create_files(search_config: &Search, destination: &Path, book: &Book) -> Result<()> {
let mut index = Index::new(&["title", "body", "breadcrumbs"]);
let mut index = IndexBuilder::new()
.add_field_with_tokenizer("title", Box::new(&tokenize))
.add_field_with_tokenizer("body", Box::new(&tokenize))
.add_field_with_tokenizer("breadcrumbs", Box::new(&tokenize))
.build();
let mut doc_urls = Vec::with_capacity(book.sections.len());
for item in book.iter() {
@ -211,12 +227,13 @@ fn write_to_json(index: Index, search_config: &Search, doc_urls: Vec<String>) ->
let mut fields = BTreeMap::new();
let mut opt = SearchOptionsField::default();
opt.boost = Some(search_config.boost_title);
fields.insert("title".into(), opt);
opt.boost = Some(search_config.boost_paragraph);
fields.insert("body".into(), opt);
opt.boost = Some(search_config.boost_hierarchy);
fields.insert("breadcrumbs".into(), opt);
let mut insert_boost = |key: &str, boost| {
opt.boost = Some(boost);
fields.insert(key.into(), opt);
};
insert_boost("title", search_config.boost_title);
insert_boost("body", search_config.boost_paragraph);
insert_boost("breadcrumbs", search_config.boost_hierarchy);
let search_options = SearchOptions {
bool: if search_config.use_boolean_and {

View File

@ -8,7 +8,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
overflow-x: auto;
background: #191f26;
color: #e6e1cf;
padding: 0.5em;
}
.hljs-comment,

View File

@ -208,24 +208,63 @@ pre {
pre > .buttons {
position: absolute;
z-index: 100;
right: 5px;
top: 5px;
right: 0px;
top: 2px;
margin: 0px;
padding: 2px 0px;
color: var(--sidebar-fg);
cursor: pointer;
visibility: hidden;
opacity: 0;
transition: visibility 0.1s linear, opacity 0.1s linear;
}
pre:hover > .buttons {
visibility: visible;
opacity: 1
}
pre > .buttons :hover {
color: var(--sidebar-active);
border-color: var(--icons-hover);
background-color: var(--theme-hover);
}
pre > .buttons i {
margin-left: 8px;
}
pre > .buttons button {
color: inherit;
background: transparent;
border: none;
cursor: inherit;
margin: 0px 5px;
padding: 3px 5px;
font-size: 14px;
border-style: solid;
border-width: 1px;
border-radius: 4px;
border-color: var(--icons);
background-color: var(--theme-popup-bg);
transition: 100ms;
transition-property: color,border-color,background-color;
color: var(--icons);
}
@media (pointer: coarse) {
pre > .buttons button {
/* On mobile, make it easier to tap buttons. */
padding: 0.3rem 1rem;
}
}
code {
padding: 1rem;
}
/* FIXME: ACE editors overlap their buttons because ACE does absolute
positioning within the code block which breaks padding. The only solution I
can think of is to move the padding to the outer pre tag (or insert a div
wrapper), but that would require fixing a whole bunch of CSS rules.
*/
.hljs.ace_editor {
padding: 0rem 0rem;
}
pre > .result {
margin-top: 10px;
}

View File

@ -26,6 +26,16 @@ code {
font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
}
/* make long words/inline code not x overflow */
main {
overflow-wrap: break-word;
}
/* make wide tables scroll if they overflow */
.table-wrapper {
overflow-x: auto;
}
/* Don't change font size in headers. */
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-size: unset;
@ -80,8 +90,7 @@ h6:target::before {
.content {
overflow-y: auto;
padding: 0 15px;
padding-bottom: 50px;
padding: 0 5px 50px 5px;
}
.content main {
margin-left: auto;

View File

@ -61,7 +61,6 @@
overflow-x: auto;
background: #f6f7f6;
color: #000;
padding: 0.5em;
}
.hljs-emphasis {

View File

@ -81,8 +81,6 @@
overflow-x: auto;
background: #1d1f21;
color: #c5c8c6;
padding: 0.5em;
-webkit-text-size-adjust: none;
}
.coffeescript .javascript,

View File

@ -200,12 +200,28 @@ pub fn render_markdown_with_path(text: &str, curly_quotes: bool, path: Option<&P
let p = new_cmark_parser(text, curly_quotes);
let events = p
.map(clean_codeblock_headers)
.map(|event| adjust_links(event, path));
.map(|event| adjust_links(event, path))
.flat_map(|event| {
let (a, b) = wrap_tables(event);
a.into_iter().chain(b)
});
html::push_html(&mut s, events);
s
}
/// Wraps tables in a `.table-wrapper` class to apply overflow-x rules to.
fn wrap_tables(event: Event<'_>) -> (Option<Event<'_>>, Option<Event<'_>>) {
match event {
Event::Start(Tag::Table(_)) => (
Some(Event::Html(r#"<div class="table-wrapper">"#.into())),
Some(event),
),
Event::End(Tag::Table(_)) => (Some(event), Some(Event::Html(r#"</div>"#.into()))),
_ => (Some(event), None),
}
}
fn clean_codeblock_headers(event: Event<'_>) -> Event<'_> {
match event {
Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(ref info))) => {
@ -282,6 +298,22 @@ mod tests {
);
}
#[test]
fn it_can_wrap_tables() {
let src = r#"
| Original | Punycode | Punycode + Encoding |
|-----------------|-----------------|---------------------|
| føø | f-5gaa | f_5gaa |
"#;
let out = r#"
<div class="table-wrapper"><table><thead><tr><th>Original</th><th>Punycode</th><th>Punycode + Encoding</th></tr></thead><tbody>
<tr><td>føø</td><td>f-5gaa</td><td>f_5gaa</td></tr>
</tbody></table>
</div>
"#.trim();
assert_eq!(render_markdown(src, false), out);
}
#[test]
fn it_can_keep_quotes_straight() {
assert_eq!(render_markdown("'one'", false), "<p>'one'</p>\n");

View File

@ -122,6 +122,7 @@ mod tests {
};
#[test]
#[allow(clippy::reversed_empty_ranges)] // Intentionally checking that those are correctly handled
fn take_lines_test() {
let s = "Lorem\nipsum\ndolor\nsit\namet";
assert_eq!(take_lines(s, 1..3), "ipsum\ndolor");
@ -163,6 +164,7 @@ mod tests {
}
#[test]
#[allow(clippy::reversed_empty_ranges)] // Intentionally checking that those are correctly handled
fn take_rustdoc_include_lines_test() {
let s = "Lorem\nipsum\ndolor\nsit\namet";
assert_eq!(

View File

@ -0,0 +1,11 @@
# Summary
---
- [None of these should be treated as the "index chapter"]()
# Part 1
- [Not this either]()
- [Chapter 1](./chapter_1.md)
- [And not this]()

View File

@ -0,0 +1 @@
# Chapter 1

View File

@ -1,3 +1,5 @@
Capybara capybara capybara.
Capybara capybara capybara.
Capybara capybara capybara.
ThisLongWordIsIncludedSoWeCanCheckThatSufficientlyLongWordsAreOmittedFromTheSearchIndex.

View File

@ -467,6 +467,21 @@ fn by_default_mdbook_use_index_preprocessor_to_convert_readme_to_index() {
assert_doesnt_contain_strings(&second_index, &unexpected_strings);
}
#[test]
fn first_chapter_is_copied_as_index_even_if_not_first_elem() {
let temp = DummyBook::new().build().unwrap();
let mut cfg = Config::default();
cfg.set("book.src", "index_html_test")
.expect("Couldn't set config.book.src to \"index_html_test\"");
let md = MDBook::load_with_config(temp.path(), cfg).unwrap();
md.build().unwrap();
let root = temp.path().join("book");
let chapter = fs::read_to_string(root.join("chapter_1.html")).expect("read chapter 1");
let index = fs::read_to_string(root.join("index.html")).expect("read index");
pretty_assertions::assert_eq!(chapter, index);
}
#[test]
fn theme_dir_overrides_work_correctly() {
let book_dir = dummy_book::new_copy_of_example_book().unwrap();
@ -772,7 +787,7 @@ mod search {
);
assert_eq!(
docs[&no_headers]["body"],
"Capybara capybara capybara. Capybara capybara capybara."
"Capybara capybara capybara. Capybara capybara capybara. ThisLongWordIsIncludedSoWeCanCheckThatSufficientlyLongWordsAreOmittedFromTheSearchIndex."
);
}

View File

@ -241,7 +241,7 @@
"title": "Unicode stress tests"
},
"19": {
"body": "Capybara capybara capybara. Capybara capybara capybara.",
"body": "Capybara capybara capybara. Capybara capybara capybara. ThisLongWordIsIncludedSoWeCanCheckThatSufficientlyLongWordsAreOmittedFromTheSearchIndex.",
"breadcrumbs": "First Chapter » No Headers",
"id": "19",
"title": "First Chapter"