Compare commits

..

2 Commits

Author SHA1 Message Date
Eric Huss
f66df09324 Bump 0.4.5 2021-01-04 07:03:20 -08:00
Pietro Albini
648c9ae772 fix xss in the search page
Thanks to Kamil Vavra for responsibly disclosing the vulnerability
according to Rust's Security Policy.
2021-01-04 07:01:49 -08:00
34 changed files with 193 additions and 538 deletions

View File

@@ -1,63 +1,5 @@
# Changelog
## mdBook 0.4.7
[9a9eb01...c83bbd6](https://github.com/rust-lang/mdBook/compare/9a9eb01...c83bbd6)
### Changed
- Updated shlex parser to fix a minor parsing issue (used by the
preprocessor/backend custom command config).
[#1471](https://github.com/rust-lang/mdBook/pull/1471)
- Enhanced text contrast of `light` theme to improve accessibility.
[#1470](https://github.com/rust-lang/mdBook/pull/1470)
### Fixed
- Fixed some issues with fragment scrolling and linking.
[#1463](https://github.com/rust-lang/mdBook/pull/1463)
## mdBook 0.4.6
[eaa6914...1a0c296](https://github.com/rust-lang/mdBook/compare/eaa6914...1a0c296)
### Changed
- The chapter name is now included in the search breadcrumbs.
[#1389](https://github.com/rust-lang/mdBook/pull/1389)
- Pressing Escape will remove the `?highlight` argument from the URL.
[#1427](https://github.com/rust-lang/mdBook/pull/1427)
- `mdbook init --theme` will now place the theme in the root of the book
directory instead of in the `src` directory.
[#1432](https://github.com/rust-lang/mdBook/pull/1432)
- A custom renderer that sets the `command` to a relative path now interprets
the relative path relative to the book root. Previously it was inconsistent
based on the platform (either relative to the current directory, or relative
to the renderer output directory). Paths relative to the output directory
are still supported with a deprecation warning.
[#1418](https://github.com/rust-lang/mdBook/pull/1418)
- The `theme` directory in the config is now interpreted as relative to the
book root, instead of the current directory.
[#1405](https://github.com/rust-lang/mdBook/pull/1405)
- Handle UTF-8 BOM for chapter sources.
[#1285](https://github.com/rust-lang/mdBook/pull/1285)
- Removed extra whitespace added to `{{#playground}}` snippets.
[#1375](https://github.com/rust-lang/mdBook/pull/1375)
### Fixed
- Clicking on a search result with multiple search words will now correctly
highlight all of the words.
[#1426](https://github.com/rust-lang/mdBook/pull/1426)
- Properly handle `<` and `>` characters in the table of contents.
[#1376](https://github.com/rust-lang/mdBook/pull/1376)
- Fixed to properly serialize the `build` table in the config, which prevented
setting it in the API.
[#1378](https://github.com/rust-lang/mdBook/pull/1378)
## mdBook 0.4.5
[eaa6914...f66df09](https://github.com/rust-lang/mdBook/compare/eaa6914...f66df09)
### Fixed
- Fixed XSS in the search page.
[CVE-2020-26297](https://groups.google.com/g/rustlang-security-announcements/c/3-sO6of29O0)
[648c9ae](https://github.com/rust-lang/mdBook/commit/648c9ae772bec83f0a5954d17b4287d5bb1d6606)
## mdBook 0.4.4
[4df9ec9...01836ba](https://github.com/rust-lang/mdBook/compare/4df9ec9...01836ba)

6
Cargo.lock generated
View File

@@ -723,7 +723,7 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "mdbook"
version = "0.4.7"
version = "0.4.5"
dependencies = [
"ammonia",
"anyhow",
@@ -1258,9 +1258,9 @@ dependencies = [
[[package]]
name = "shlex"
version = "1.0.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "siphasher"

View File

@@ -1,6 +1,6 @@
[package]
name = "mdbook"
version = "0.4.7"
version = "0.4.5"
authors = [
"Mathieu David <mathieudavid@mathieudavid.org>",
"Michael-F-Bryan <michaelfbryan@gmail.com>",
@@ -30,7 +30,7 @@ regex = "1.0.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
shlex = "1"
shlex = "0.1"
tempfile = "3.0"
toml = "0.5.1"

View File

@@ -91,11 +91,10 @@ all its functionality as a Rust crate for integration in other projects.
Here are the main commands you will want to run. For a more exhaustive
explanation, check out the [User Guide].
- `mdbook init <directory>`
- `mdbook init`
The init command will create a directory with the minimal boilerplate to
start with. If the `<directory>` parameter is omitted, the current
directory will be used.
start with.
```
book-test/
@@ -150,7 +149,6 @@ preprocessors are:
the url `foo/` when published to a browser
- `links` - a built-in preprocessor (enabled by default) for expanding the
`{{# playground}}` and `{{# include}}` helpers in a chapter.
- [`katex`](https://github.com/lzanini/mdbook-katex) - a preprocessor rendering LaTex equations to HTML.
Renderers are given the final book so they can do something with it. This is
typically used for, as the name suggests, rendering the document in a particular

View File

@@ -10,7 +10,6 @@ edition = "2018"
[output.html]
mathjax-support = true
site-url = "/mdBook/"
git-repository-url = "https://github.com/rust-lang/mdBook/tree/master/guide"
[output.html.playground]
editable = true

View File

@@ -12,7 +12,7 @@ to download the appropriate version for your platform.
## Install From Source
mdBook can also be installed by compiling the source code on your local machine.
mdBook can also be installed from source
### Pre-requisite

View File

@@ -39,9 +39,6 @@ permissions (or "repo" for private repositories). Go to your repository's Travis
CI settings page and add an environment variable named `GITHUB_TOKEN` that is
marked secure and *not* shown in the logs.
Whilst still in your repository's settings page, navigate to Options and change the
Source on GitHub pages to `gh-pages`.
Then, append this snippet to your `.travis.yml` and update the path to the
`book` directory:
@@ -58,40 +55,6 @@ deploy:
That's it!
Note: Travis has a new [dplv2](https://blog.travis-ci.com/2019-08-27-deployment-tooling-dpl-v2-preview-release) configuration that is currently in beta. To use this new format, update your `.travis.yml` file to:
```yaml
language: rust
os: linux
dist: xenial
cache:
- cargo
rust:
- stable
before_script:
- (test -x $HOME/.cargo/bin/cargo-install-update || cargo install cargo-update)
- (test -x $HOME/.cargo/bin/mdbook || cargo install --vers "^0.3" mdbook)
- cargo install-update -a
script:
- mdbook build path/to/mybook && mdbook test path/to/mybook
deploy:
provider: pages
strategy: git
edge: true
cleanup: false
github-token: $GITHUB_TOKEN
local-dir: path/to/mybook/book
keep-history: false
on:
branch: master
target_branch: gh-pages
```
### Deploying to GitHub Pages manually
If your CI doesn't support GitHub pages, or you're deploying somewhere else
@@ -124,31 +87,3 @@ deploy: book
git commit -m "deployed on $(shell date) by ${USER}" && \
git push origin gh-pages
```
## Deploying Your Book to GitLab Pages
Inside your repository's project root, create a file named `.gitlab-ci.yml` with the following contents:
```yml
stages:
- deploy
pages:
stage: deploy
image: rust:alpine
variables:
CARGO_HOME: $CI_PROJECT_DIR/cargo
before_script:
- export PATH="$PATH:$CARGO_HOME/bin"
- mdbook --version || cargo install mdbook
script:
- mdbook build -d public
only:
- master
artifacts:
paths:
- public
cache:
paths:
- $CARGO_HOME/bin
```
After you commit and push this new file, GitLab CI will run and your book will be available!

View File

@@ -14,11 +14,9 @@ Here are the files you can override:
- **_index.hbs_** is the handlebars template.
- **_head.hbs_** is appended to the HTML `<head>` section.
- **_header.hbs_** content is appended on top of every book page.
- **_css/_** contains the CSS files for styling the book.
- **_css/chrome.css_** is for UI elements.
- **_css/general.css_** is the base styles.
- **_css/print.css_** is the style for printer output.
- **_css/variables.css_** contains variables used in other CSS files.
- **_book.css_** is the style used in the output. If you want to change the
design of your book, this is probably the file you want to modify. Sometimes
in conjunction with `index.hbs` when you want to radically change the layout.
- **_book.js_** is mostly used to add client side functionality, like hiding /
un-hiding the sidebar, changing the theme, ...
- **_highlight.js_** is the JavaScript that is used to highlight code snippets,

View File

@@ -19,7 +19,7 @@ Here is a list of the properties that are exposed:
- ***language*** Language of the book in the form `en`, as specified in `book.toml` (if not specified, defaults to `en`). To use in <code
class="language-html">\<html lang="{{ language }}"></code> for example.
- ***title*** Title used for the current page. This is identical to `{{ chapter_title }} - {{ book_title }}` unless `book_title` is not set in which case it just defaults to the `chapter_title`.
- ***title*** Title used for the current page. This is identical to `{{ book_title }} - {{ chapter_title }}` unless `book_title` is not set in which case it just defaults to the `chapter_title`.
- ***book_title*** Title of the book, as specified in `book.toml`
- ***chapter_title*** Title of the current chapter, as listed in `SUMMARY.md`

View File

@@ -112,10 +112,10 @@ everyone can benefit from it.**
## Improve default theme
If you think the default theme doesn't look quite right for a specific language,
or could be improved, feel free to [submit a new
or could be improved. Feel free to [submit a new
issue](https://github.com/rust-lang/mdBook/issues) explaining what you
have in mind and I will take a look at it.
You could also create a pull-request with the proposed improvements.
Overall the theme should be light and sober, without too many flashy colors.
Overall the theme should be light and sober, without to many flashy colors.

View File

@@ -16,6 +16,5 @@ shout-out to them!
- [Phaiax](https://github.com/Phaiax)
- Matt Ickstadt ([mattico](https://github.com/mattico))
- Weihang Lo ([@weihanglo](https://github.com/weihanglo))
- Avision Ho ([@avisionh](https://github.com/avisionh))
If you feel you're missing from this list, feel free to add yourself in a PR.
If you feel you're missing from this list, feel free to add yourself in a PR.

View File

@@ -14,12 +14,11 @@ pub fn load_book<P: AsRef<Path>>(src_dir: P, cfg: &BuildConfig) -> Result<Book>
let summary_md = src_dir.join("SUMMARY.md");
let mut summary_content = String::new();
File::open(&summary_md)
.with_context(|| format!("Couldn't open SUMMARY.md in {:?} directory", src_dir))?
File::open(summary_md)
.with_context(|| "Couldn't open SUMMARY.md")?
.read_to_string(&mut summary_content)?;
let summary = parse_summary(&summary_content)
.with_context(|| format!("Summary parsing failed for file={:?}", summary_md))?;
let summary = parse_summary(&summary_content).with_context(|| "Summary parsing failed")?;
if cfg.create_missing {
create_missing(&src_dir, &summary).with_context(|| "Unable to create missing chapters")?;
@@ -50,9 +49,7 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
}
debug!("Creating missing file {}", filename.display());
let mut f = File::create(&filename).with_context(|| {
format!("Unable to create missing file: {}", filename.display())
})?;
let mut f = File::create(&filename)?;
writeln!(f, "# {}", link.name)?;
}
}
@@ -66,7 +63,7 @@ fn create_missing(src_dir: &Path, summary: &Summary) -> Result<()> {
/// A dumb tree structure representing a book.
///
/// For the moment a book is just a collection of [`BookItems`] which are
/// For the moment a book is just a collection of `BookItems` which are
/// accessible by either iterating (immutably) over the book with [`iter()`], or
/// recursively applying a closure to each section to mutate the chapters, using
/// [`for_each_mut()`].
@@ -160,7 +157,7 @@ pub struct Chapter {
pub sub_items: Vec<BookItem>,
/// The chapter's location, relative to the `SUMMARY.md` file.
pub path: Option<PathBuf>,
/// An ordered list of the names of each chapter above this one in the hierarchy.
/// An ordered list of the names of each chapter above this one, in the hierarchy.
pub parent_names: Vec<String>,
}
@@ -181,8 +178,8 @@ impl Chapter {
}
}
/// Create a new draft chapter that is not attached to a source markdown file (and thus
/// has no content).
/// Create a new draft chapter that is not attached to a source markdown file and has
/// thus no content.
pub fn new_draft(name: &str, parent_names: Vec<String>) -> Self {
Chapter {
name: name.to_string(),
@@ -193,7 +190,7 @@ impl Chapter {
}
}
/// Check if the chapter is a draft chapter, meaning it has no path to a source markdown file.
/// Check if the chapter is a draft chapter, meaning it has no path to a source markdown file
pub fn is_draft_chapter(&self) -> bool {
match self.path {
Some(_) => false,
@@ -267,10 +264,6 @@ fn load_chapter<P: AsRef<Path>>(
format!("Unable to read \"{}\" ({})", link.name, location.display())
})?;
if content.as_bytes().starts_with(b"\xef\xbb\xbf") {
content.replace_range(..3, "");
}
let stripped = location
.strip_prefix(&src_dir)
.expect("Chapters are always inside a book");
@@ -280,7 +273,7 @@ fn load_chapter<P: AsRef<Path>>(
Chapter::new_draft(&link.name, parent_names.clone())
};
let mut sub_item_parents = parent_names;
let mut sub_item_parents = parent_names.clone();
ch.number = link.number.clone();
@@ -302,6 +295,8 @@ fn load_chapter<P: AsRef<Path>>(
///
/// This struct shouldn't be created directly, instead prefer the
/// [`Book::iter()`] method.
///
/// [`Book::iter()`]: struct.Book.html#method.iter
pub struct BookItems<'a> {
items: VecDeque<&'a BookItem>,
}
@@ -398,29 +393,6 @@ And here is some \
assert_eq!(got, should_be);
}
#[test]
fn load_a_single_chapter_with_utf8_bom_from_disk() {
let temp_dir = TempFileBuilder::new().prefix("book").tempdir().unwrap();
let chapter_path = temp_dir.path().join("chapter_1.md");
File::create(&chapter_path)
.unwrap()
.write_all(("\u{feff}".to_owned() + DUMMY_SRC).as_bytes())
.unwrap();
let link = Link::new("Chapter 1", chapter_path);
let should_be = Chapter::new(
"Chapter 1",
DUMMY_SRC.to_string(),
"chapter_1.md",
Vec::new(),
);
let got = load_chapter(&link, temp_dir.path(), Vec::new()).unwrap();
assert_eq!(got, should_be);
}
#[test]
fn cant_load_a_nonexistent_chapter() {
let link = Link::new("Chapter 1", "/foo/bar/baz.md");

View File

@@ -28,7 +28,7 @@ impl BookBuilder {
}
}
/// Set the [`Config`] to be used.
/// Set the `Config` to be used.
pub fn with_config(&mut self, cfg: Config) -> &mut BookBuilder {
self.config = cfg;
self
@@ -110,7 +110,10 @@ impl BookBuilder {
debug!("Copying theme");
let html_config = self.config.html_config().unwrap_or_default();
let themedir = html_config.theme_dir(&self.root);
let themedir = html_config
.theme
.unwrap_or_else(|| self.config.book.src.join("theme"));
let themedir = self.root.join(themedir);
if !themedir.exists() {
debug!(
@@ -124,9 +127,7 @@ impl BookBuilder {
index.write_all(theme::INDEX)?;
let cssdir = themedir.join("css");
if !cssdir.exists() {
fs::create_dir(&cssdir)?;
}
fs::create_dir(&cssdir)?;
let mut general_css = File::create(cssdir.join("general.css"))?;
general_css.write_all(theme::GENERAL_CSS)?;

View File

@@ -40,7 +40,7 @@ pub struct MDBook {
pub book: Book,
renderers: Vec<Box<dyn Renderer>>,
/// List of pre-processors to be run on the book.
/// List of pre-processors to be run on the book
preprocessors: Vec<Box<dyn Preprocessor>>,
}
@@ -78,7 +78,7 @@ impl MDBook {
MDBook::load_with_config(book_root, config)
}
/// Load a book from its root directory using a custom `Config`.
/// Load a book from its root directory using a custom config.
pub fn load_with_config<P: Into<PathBuf>>(book_root: P, config: Config) -> Result<MDBook> {
let root = book_root.into();
@@ -97,7 +97,7 @@ impl MDBook {
})
}
/// Load a book from its root directory using a custom `Config` and a custom summary.
/// Load a book from its root directory using a custom config and a custom summary.
pub fn load_with_config_and_summary<P: Into<PathBuf>>(
book_root: P,
config: Config,
@@ -121,7 +121,7 @@ impl MDBook {
}
/// Returns a flat depth-first iterator over the elements of the book,
/// it returns a [`BookItem`] enum:
/// it returns an [BookItem enum](bookitem.html):
/// `(section: String, bookitem: &BookItem)`
///
/// ```no_run
@@ -180,7 +180,7 @@ impl MDBook {
Ok(())
}
/// Run the entire build process for a particular [`Renderer`].
/// Run the entire build process for a particular `Renderer`.
pub fn execute_build_process(&self, renderer: &dyn Renderer) -> Result<()> {
let mut preprocessed_book = self.book.clone();
let preprocess_ctx = PreprocessorContext::new(
@@ -219,14 +219,14 @@ impl MDBook {
}
/// You can change the default renderer to another one by using this method.
/// The only requirement is that your renderer implement the [`Renderer`]
/// trait.
/// The only requirement is for your renderer to implement the [`Renderer`
/// trait](../renderer/trait.Renderer.html)
pub fn with_renderer<R: Renderer + 'static>(&mut self, renderer: R) -> &mut Self {
self.renderers.push(Box::new(renderer));
self
}
/// Register a [`Preprocessor`] to be used when rendering the book.
/// Register a [`Preprocessor`](../preprocess/trait.Preprocessor.html) to be used when rendering the book.
pub fn with_preprocessor<P: Preprocessor + 'static>(&mut self, preprocessor: P) -> &mut Self {
self.preprocessors.push(Box::new(preprocessor));
self
@@ -303,7 +303,7 @@ impl MDBook {
/// artefacts.
///
/// If there is only 1 renderer, put it in the directory pointed to by the
/// `build.build_dir` key in [`Config`]. If there is more than one then the
/// `build.build_dir` key in `Config`. If there is more than one then the
/// renderer gets its own directory within the main build dir.
///
/// i.e. If there were only one renderer (in this case, the HTML renderer):

View File

@@ -28,11 +28,15 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
// If flag `--theme` is present, copy theme to src
if args.is_present("theme") {
let theme_dir = book_dir.join("theme");
println!();
println!("Copying the default theme to {}", theme_dir.display());
config.set("output.html.theme", "src/theme")?;
// Skip this if `--force` is present
if !args.is_present("force") && theme_dir.exists() {
if !args.is_present("force") {
// Print warning
println!();
println!(
"Copying the default theme to {}",
builder.config().book.src.display()
);
println!("This could potentially overwrite files already present in that directory.");
print!("\nAre you sure you want to continue? (y/n) ");

View File

@@ -2,7 +2,7 @@
//!
//! The main entrypoint of the `config` module is the `Config` struct. This acts
//! essentially as a bag of configuration information, with a couple
//! pre-determined tables ([`BookConfig`] and [`BuildConfig`]) as well as support
//! pre-determined tables (`BookConfig` and `BuildConfig`) as well as support
//! for arbitrary data which is exposed to plugins and alternative backends.
//!
//!
@@ -352,11 +352,6 @@ impl Serialize for Config {
let book_config = Value::try_from(&self.book).expect("should always be serializable");
table.insert("book", book_config);
if self.build != BuildConfig::default() {
let build_config = Value::try_from(&self.build).expect("should always be serializable");
table.insert("build", build_config);
}
if self.rust != RustConfig::default() {
let rust_config = Value::try_from(&self.rust).expect("should always be serializable");
table.insert("rust", rust_config);

View File

@@ -76,9 +76,9 @@
//! access to the various methods for working with the [`Config`].
//!
//! [user guide]: https://rust-lang.github.io/mdBook/
//! [`RenderContext`]: renderer::RenderContext
//! [`RenderContext`]: renderer/struct.RenderContext.html
//! [relevant chapter]: https://rust-lang.github.io/mdBook/for_developers/backends.html
//! [`Config`]: config::Config
//! [`Config`]: config/struct.Config.html
#![deny(missing_docs)]
#![deny(rust_2018_idioms)]

View File

@@ -335,7 +335,7 @@ impl<'a> Link<'a> {
LinkType::Playground(ref pat, ref attrs) => {
let target = base.join(pat);
let mut contents = fs::read_to_string(&target).with_context(|| {
let contents = fs::read_to_string(&target).with_context(|| {
format!(
"Could not read file for link {} ({})",
self.link_text,
@@ -343,11 +343,8 @@ impl<'a> Link<'a> {
)
})?;
let ftype = if !attrs.is_empty() { "rust," } else { "rust" };
if !contents.ends_with('\n') {
contents.push('\n');
}
Ok(format!(
"```{}{}\n{}```\n",
"```{}{}\n{}\n```\n",
ftype,
attrs.join(","),
contents

View File

@@ -366,7 +366,7 @@ impl HtmlHandlebars {
// Note: all paths are relative to the build directory, so the
// leading slash in an absolute path means nothing (and would mess
// up `root.join(original)`).
let original = original.trim_start_matches('/');
let original = original.trim_start_matches("/");
let filename = root.join(original);
self.emit_redirect(handlebars, &filename, new)?;
}
@@ -452,7 +452,7 @@ impl Renderer for HtmlHandlebars {
let mut handlebars = Handlebars::new();
let theme_dir = match html_config.theme {
Some(ref theme) => ctx.root.join(theme),
Some(ref theme) => theme.to_path_buf(),
None => ctx.root.join("theme"),
};
@@ -756,7 +756,7 @@ fn insert_link_into_header(
*id_count += 1;
format!(
r##"<h{level} id="{id}"><a class="header" href="#{id}">{text}</a></h{level}>"##,
r##"<h{level}><a class="header" href="#{id}" id="{id}">{text}</a></h{level}>"##,
level = level,
id = id,
text = content
@@ -899,10 +899,10 @@ fn partition_source(s: &str) -> (String, String) {
if !header || after_header {
after_header = true;
after.push_str(line);
after.push('\n');
after.push_str("\n");
} else {
before.push_str(line);
before.push('\n');
before.push_str("\n");
}
}
@@ -927,27 +927,27 @@ mod tests {
let inputs = vec![
(
"blah blah <h1>Foo</h1>",
r##"blah blah <h1 id="foo"><a class="header" href="#foo">Foo</a></h1>"##,
r##"blah blah <h1><a class="header" href="#foo" id="foo">Foo</a></h1>"##,
),
(
"<h1>Foo</h1>",
r##"<h1 id="foo"><a class="header" href="#foo">Foo</a></h1>"##,
r##"<h1><a class="header" href="#foo" id="foo">Foo</a></h1>"##,
),
(
"<h3>Foo^bar</h3>",
r##"<h3 id="foobar"><a class="header" href="#foobar">Foo^bar</a></h3>"##,
r##"<h3><a class="header" href="#foobar" id="foobar">Foo^bar</a></h3>"##,
),
(
"<h4></h4>",
r##"<h4 id=""><a class="header" href="#"></a></h4>"##,
r##"<h4><a class="header" href="#" id=""></a></h4>"##,
),
(
"<h4><em>Hï</em></h4>",
r##"<h4 id="hï"><a class="header" href="#hï"><em>Hï</em></a></h4>"##,
r##"<h4><a class="header" href="#hï" id="hï"><em>Hï</em></a></h4>"##,
),
(
"<h1>Foo</h1><h3>Foo</h3>",
r##"<h1 id="foo"><a class="header" href="#foo">Foo</a></h1><h3 id="foo-1"><a class="header" href="#foo-1">Foo</a></h3>"##,
r##"<h1><a class="header" href="#foo" id="foo">Foo</a></h1><h3><a class="header" href="#foo-1" id="foo-1">Foo</a></h3>"##,
),
];

View File

@@ -1,5 +1,4 @@
use std::collections::BTreeMap;
use std::io;
use std::path::Path;
use crate::utils;
@@ -103,7 +102,7 @@ impl HelperDef for RenderToc {
// Part title
if let Some(title) = item.get("part") {
out.write("<li class=\"part-title\">")?;
write_escaped(out, title)?;
out.write(title)?;
out.write("</li>")?;
continue;
}
@@ -161,7 +160,7 @@ impl HelperDef for RenderToc {
html::push_html(&mut markdown_parsed_name, parser);
// write to the handlebars template
write_escaped(out, &markdown_parsed_name)?;
out.write(&markdown_parsed_name)?;
}
if path_exists {
@@ -205,18 +204,3 @@ fn write_li_open_tag(
li.push_str("\">");
out.write(&li)
}
fn write_escaped(out: &mut dyn Output, mut title: &str) -> io::Result<()> {
let needs_escape: &[char] = &['<', '>'];
while let Some(next) = title.find(needs_escape) {
out.write(&title[..next])?;
match title.as_bytes()[next] {
b'<' => out.write("&lt;")?,
b'>' => out.write("&gt;")?,
_ => unreachable!(),
}
title = &title[next + 1..];
}
out.write(title)?;
Ok(())
}

View File

@@ -95,8 +95,6 @@ fn render_item(
let mut breadcrumbs = chapter.parent_names.clone();
let mut footnote_numbers = HashMap::new();
breadcrumbs.push(chapter.name.clone());
while let Some(event) = p.next() {
match event {
Event::Start(Tag::Heading(i)) if i <= max_section_depth => {

View File

@@ -20,7 +20,7 @@ mod markdown_renderer;
use shlex::Shlex;
use std::fs;
use std::io::{self, ErrorKind, Read};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::process::{Command, Stdio};
use crate::book::Book;
@@ -34,9 +34,12 @@ use toml::Value;
/// provide your own renderer, there are two main renderer implementations that
/// 99% of users will ever use:
///
/// - [`HtmlHandlebars`] - the built-in HTML renderer
/// - [`CmdRenderer`] - a generic renderer which shells out to a program to do the
/// - [HtmlHandlebars] - the built-in HTML renderer
/// - [CmdRenderer] - a generic renderer which shells out to a program to do the
/// actual rendering
///
/// [HtmlHandlebars]: struct.HtmlHandlebars.html
/// [CmdRenderer]: struct.CmdRenderer.html
pub trait Renderer {
/// The `Renderer`'s name.
fn name(&self) -> &str;
@@ -130,44 +133,14 @@ impl CmdRenderer {
CmdRenderer { name, cmd }
}
fn compose_command(&self, root: &Path, destination: &Path) -> Result<Command> {
fn compose_command(&self) -> Result<Command> {
let mut words = Shlex::new(&self.cmd);
let exe = match words.next() {
Some(e) => PathBuf::from(e),
let executable = match words.next() {
Some(e) => e,
None => bail!("Command string was empty"),
};
let exe = if exe.components().count() == 1 {
// Search PATH for the executable.
exe
} else {
// Relative paths are preferred to be relative to the book root.
let abs_exe = root.join(&exe);
if abs_exe.exists() {
abs_exe
} else {
// Historically paths were relative to the destination, but
// this is not the preferred way.
let legacy_path = destination.join(&exe);
if legacy_path.exists() {
warn!(
"Renderer command `{}` uses a path relative to the \
renderer output directory `{}`. This was previously \
accepted, but has been deprecated. Relative executable \
paths should be relative to the book root.",
exe.display(),
destination.display()
);
legacy_path
} else {
// Let this bubble through to later be handled by
// handle_render_command_error.
abs_exe.to_path_buf()
}
}
};
let mut cmd = Command::new(exe);
let mut cmd = Command::new(executable);
for arg in words {
cmd.arg(arg);
@@ -222,7 +195,7 @@ impl Renderer for CmdRenderer {
let _ = fs::create_dir_all(&ctx.destination);
let mut child = match self
.compose_command(&ctx.root, &ctx.destination)?
.compose_command()?
.stdin(Stdio::piped())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())

View File

@@ -93,7 +93,7 @@ a > .hljs {
.menu-title {
display: inline-block;
font-weight: 200;
font-size: 2.4rem;
font-size: 2rem;
line-height: var(--menu-bar-height);
text-align: center;
margin: 0;

View File

@@ -45,23 +45,20 @@ h4, h5 { margin-top: 2em; }
margin-top: 1em;
}
h1:target::before,
h2:target::before,
h3:target::before,
h4:target::before,
h5:target::before,
h6:target::before {
h1 a.header:target::before,
h2 a.header:target::before,
h3 a.header:target::before,
h4 a.header:target::before {
display: inline-block;
content: "»";
margin-left: -30px;
width: 30px;
}
/* This is broken on Safari as of version 14, but is fixed
in Safari Technology Preview 117 which I think will be Safari 14.2.
https://bugs.webkit.org/show_bug.cgi?id=218076
*/
:target {
h1 a.header:target,
h2 a.header:target,
h3 a.header:target,
h4 a.header:target {
scroll-margin-top: calc(var(--menu-bar-height) + 0.5em);
}

View File

@@ -92,22 +92,22 @@
.light {
--bg: hsl(0, 0%, 100%);
--fg: hsl(0, 0%, 0%);
--fg: #333333;
--sidebar-bg: #fafafa;
--sidebar-fg: hsl(0, 0%, 0%);
--sidebar-fg: #364149;
--sidebar-non-existant: #aaaaaa;
--sidebar-active: #1f1fff;
--sidebar-active: #008cff;
--sidebar-spacer: #f4f4f4;
--scrollbar: #8F8F8F;
--scrollbar: #cccccc;
--icons: #747474;
--icons-hover: #000000;
--icons: #cccccc;
--icons-hover: #333333;
--links: #20609f;
--links: #4183c4;
--inline-code-color: #301900;
--inline-code-color: #6e6b5e;
--theme-popup-bg: #fafafa;
--theme-popup-border: #cccccc;

View File

@@ -1,18 +1,14 @@
/*
* An increased contrast highlighting scheme loosely based on the
* "Base16 Atelier Dune Light" theme by Bram de Haan
* (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune)
* Original Base16 color scheme by Chris Kempson
* (https://github.com/chriskempson/base16)
*/
/* Base16 Atelier Dune Light - Theme */
/* by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) */
/* Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) */
/* Comment */
/* Atelier-Dune Comment */
.hljs-comment,
.hljs-quote {
color: #575757;
color: #AAA;
}
/* Red */
/* Atelier-Dune Red */
.hljs-variable,
.hljs-template-variable,
.hljs-attribute,
@@ -23,10 +19,10 @@
.hljs-name,
.hljs-selector-id,
.hljs-selector-class {
color: #d70025;
color: #d73737;
}
/* Orange */
/* Atelier-Dune Orange */
.hljs-number,
.hljs-meta,
.hljs-built_in,
@@ -34,33 +30,33 @@
.hljs-literal,
.hljs-type,
.hljs-params {
color: #b21e00;
color: #b65611;
}
/* Green */
/* Atelier-Dune Green */
.hljs-string,
.hljs-symbol,
.hljs-bullet {
color: #008200;
color: #60ac39;
}
/* Blue */
/* Atelier-Dune Blue */
.hljs-title,
.hljs-section {
color: #0030f2;
color: #6684e1;
}
/* Purple */
/* Atelier-Dune Purple */
.hljs-keyword,
.hljs-selector-tag {
color: #9d00ec;
color: #b854d4;
}
.hljs {
display: block;
overflow-x: auto;
background: #f6f7f6;
color: #000;
background: #f1f1f1;
color: #6e6b5e;
padding: 0.5em;
}

View File

@@ -296,7 +296,7 @@ window.search = window.search || {};
}
if (url.params.hasOwnProperty(URL_MARK_PARAM)) {
var words = decodeURIComponent(url.params[URL_MARK_PARAM]).split(' ');
var words = url.params[URL_MARK_PARAM].split(' ');
marker.mark(words, {
exclude: mark_exclude
});
@@ -427,7 +427,6 @@ window.search = window.search || {};
delete url.params[URL_MARK_PARAM];
url.hash = "";
} else {
delete url.params[URL_MARK_PARAM];
delete url.params[URL_SEARCH_PARAM];
}
// A new search will also add a new history item, so the user can go back

View File

@@ -110,10 +110,7 @@ pub fn copy_files_except_ext(
for entry in fs::read_dir(from)? {
let entry = entry?;
let metadata = entry
.path()
.metadata()
.with_context(|| format!("Failed to read {:?}", entry.path()))?;
let metadata = entry.path().metadata()?;
// If the entry is a dir and the recursive option is enabled, call itself
if metadata.is_dir() && recursive {

View File

@@ -70,7 +70,7 @@ pub fn take_rustdoc_include_lines<R: RangeBounds<usize>>(s: &str, range: R) -> S
output.push_str("# ");
}
output.push_str(line);
output.push('\n');
output.push_str("\n");
}
output.pop();
output
@@ -95,7 +95,7 @@ pub fn take_rustdoc_include_anchored_lines(s: &str, anchor: &str) -> String {
None => {
if !ANCHOR_START.is_match(l) {
output.push_str(l);
output.push('\n');
output.push_str("\n");
}
}
}
@@ -106,7 +106,7 @@ pub fn take_rustdoc_include_anchored_lines(s: &str, anchor: &str) -> String {
} else if !ANCHOR_END.is_match(l) {
output.push_str("# ");
output.push_str(l);
output.push('\n');
output.push_str("\n");
}
}

View File

@@ -53,7 +53,7 @@ impl TomlExt for Value {
}
fn split(key: &str) -> Option<(&str, &str)> {
let ix = key.find('.')?;
let ix = key.find(".")?;
let (head, tail) = key.split_at(ix);
// splitting will leave the "."

View File

@@ -2,7 +2,7 @@
use mdbook::config::Config;
use mdbook::MDBook;
use std::fs;
#[cfg(not(windows))]
use std::path::Path;
use tempfile::{Builder as TempFileBuilder, TempDir};
@@ -71,45 +71,6 @@ fn backends_receive_render_context_via_stdin() {
assert!(got.is_ok());
}
#[test]
fn relative_command_path() {
// Checks behavior of relative paths for the `command` setting.
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
let renderers = temp.path().join("renderers");
fs::create_dir(&renderers).unwrap();
rust_exe(
&renderers,
"myrenderer",
r#"fn main() {
std::fs::write("output", "test").unwrap();
}"#,
);
let do_test = |cmd_path| {
let mut config = Config::default();
config
.set("output.html", toml::value::Table::new())
.unwrap();
config.set("output.myrenderer.command", cmd_path).unwrap();
let md = MDBook::init(&temp.path())
.with_config(config)
.build()
.unwrap();
let output = temp.path().join("book/myrenderer/output");
assert!(!output.exists());
md.build().unwrap();
assert!(output.exists());
fs::remove_file(output).unwrap();
};
// Legacy paths work, relative to the output directory.
if cfg!(windows) {
do_test("../../renderers/myrenderer.exe");
} else {
do_test("../../renderers/myrenderer");
}
// Modern path, relative to the book directory.
do_test("renderers/myrenderer");
}
fn dummy_book_with_backend(
name: &str,
command: &str,
@@ -151,14 +112,3 @@ fn success_cmd() -> &'static str {
"true"
}
}
fn rust_exe(temp: &Path, name: &str, src: &str) {
let rs = temp.join(name).with_extension("rs");
fs::write(&rs, src).unwrap();
let status = std::process::Command::new("rustc")
.arg(rs)
.current_dir(temp)
.status()
.expect("rustc should run");
assert!(status.success());
}

View File

@@ -91,12 +91,6 @@ fn run_mdbook_init_with_custom_book_and_src_locations() {
file
);
}
let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap();
assert_eq!(
contents,
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"in\"\n\n[build]\nbuild-dir = \"out\"\ncreate-missing = true\nuse-default-preprocessors = true\n"
);
}
#[test]
@@ -108,37 +102,3 @@ fn book_toml_isnt_required() {
md.build().unwrap();
}
#[test]
fn copy_theme() {
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
MDBook::init(temp.path()).copy_theme(true).build().unwrap();
let expected = vec![
"book.js",
"css/chrome.css",
"css/general.css",
"css/print.css",
"css/variables.css",
"favicon.png",
"favicon.svg",
"highlight.css",
"highlight.js",
"index.hbs",
];
let theme_dir = temp.path().join("theme");
let mut actual: Vec<_> = walkdir::WalkDir::new(&theme_dir)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| !e.file_type().is_dir())
.map(|e| {
e.path()
.strip_prefix(&theme_dir)
.unwrap()
.to_str()
.unwrap()
.replace('\\', "/")
})
.collect();
actual.sort();
assert_eq!(actual, expected);
}

View File

@@ -104,12 +104,12 @@ fn check_correct_cross_links_in_nested_dir() {
assert_contains_strings(
first.join("index.html"),
&[r##"<h2 id="some-section"><a class="header" href="#some-section">"##],
&[r##"href="#some-section" id="some-section""##],
);
assert_contains_strings(
first.join("nested.html"),
&[r##"<h2 id="some-section"><a class="header" href="#some-section">"##],
&[r##"href="#some-section" id="some-section""##],
);
}
@@ -373,7 +373,7 @@ fn able_to_include_files_in_chapters() {
let includes = temp.path().join("book/first/includes.html");
let summary_strings = &[
r##"<h1 id="summary"><a class="header" href="#summary">Summary</a></h1>"##,
r##"<h1><a class="header" href="#summary" id="summary">Summary</a></h1>"##,
">First Chapter</a>",
];
assert_contains_strings(&includes, summary_strings);
@@ -595,10 +595,7 @@ mod search {
docs[&summary]["body"],
"Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion"
);
assert_eq!(
docs[&summary]["breadcrumbs"],
"First Chapter » Includes » Summary"
);
assert_eq!(docs[&summary]["breadcrumbs"], "First Chapter » Summary");
assert_eq!(docs[&conclusion]["body"], "I put &lt;HTML&gt; in here!");
}

View File

@@ -27,234 +27,234 @@
"docInfo": {
"0": {
"body": 9,
"breadcrumbs": 4,
"breadcrumbs": 2,
"title": 2
},
"1": {
"body": 3,
"breadcrumbs": 2,
"breadcrumbs": 1,
"title": 1
},
"10": {
"body": 16,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
},
"11": {
"body": 3,
"breadcrumbs": 5,
"breadcrumbs": 4,
"title": 2
},
"12": {
"body": 4,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
},
"13": {
"body": 12,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
},
"14": {
"body": 2,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
},
"15": {
"body": 3,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
},
"16": {
"body": 29,
"breadcrumbs": 6,
"breadcrumbs": 5,
"title": 3
},
"17": {
"body": 20,
"breadcrumbs": 4,
"breadcrumbs": 2,
"title": 2
},
"18": {
"body": 18,
"breadcrumbs": 9,
"breadcrumbs": 7,
"title": 5
},
"19": {
"body": 0,
"breadcrumbs": 5,
"breadcrumbs": 3,
"title": 1
},
"2": {
"body": 2,
"breadcrumbs": 4,
"breadcrumbs": 2,
"title": 2
},
"20": {
"body": 3,
"breadcrumbs": 2,
"breadcrumbs": 1,
"title": 1
},
"3": {
"body": 0,
"breadcrumbs": 3,
"breadcrumbs": 1,
"title": 1
},
"4": {
"body": 4,
"breadcrumbs": 6,
"breadcrumbs": 4,
"title": 2
},
"5": {
"body": 1,
"breadcrumbs": 5,
"breadcrumbs": 3,
"title": 1
},
"6": {
"body": 21,
"breadcrumbs": 11,
"breadcrumbs": 9,
"title": 7
},
"7": {
"body": 6,
"breadcrumbs": 10,
"breadcrumbs": 8,
"title": 6
},
"8": {
"body": 6,
"breadcrumbs": 8,
"breadcrumbs": 6,
"title": 4
},
"9": {
"body": 0,
"breadcrumbs": 4,
"breadcrumbs": 3,
"title": 1
}
},
"docs": {
"0": {
"body": "This file is just here to cause the index preprocessor to run. Does a pretty good job, too.",
"breadcrumbs": "Dummy Book » Dummy Book",
"breadcrumbs": "Dummy Book",
"id": "0",
"title": "Dummy Book"
},
"1": {
"body": "Here's some interesting text...",
"breadcrumbs": "Introduction » Introduction",
"breadcrumbs": "Introduction",
"id": "1",
"title": "Introduction"
},
"10": {
"body": "Dummy Book Introduction First Chapter Nested Chapter Includes Recursive Markdown Unicode Second Chapter Nested Chapter Conclusion",
"breadcrumbs": "First Chapter » Includes » Summary",
"breadcrumbs": "First Chapter » Summary",
"id": "10",
"title": "Summary"
},
"11": {
"body": "Tests for some markdown output.",
"breadcrumbs": "First Chapter » Markdown » Markdown tests",
"breadcrumbs": "First Chapter » Markdown tests",
"id": "11",
"title": "Markdown tests"
},
"12": {
"body": "foo bar baz bim",
"breadcrumbs": "First Chapter » Markdown » Tables",
"breadcrumbs": "First Chapter » Tables",
"id": "12",
"title": "Tables"
},
"13": {
"body": "Footnote example [1] , or with a word [2] . This is a footnote. A longer footnote. With multiple lines. Third line.",
"breadcrumbs": "First Chapter » Markdown » Footnotes",
"breadcrumbs": "First Chapter » Footnotes",
"id": "13",
"title": "Footnotes"
},
"14": {
"body": "strikethrough example",
"breadcrumbs": "First Chapter » Markdown » Strikethrough",
"breadcrumbs": "First Chapter » Strikethrough",
"id": "14",
"title": "Strikethrough"
},
"15": {
"body": "Apples Broccoli Carrots",
"breadcrumbs": "First Chapter » Markdown » Tasklisks",
"breadcrumbs": "First Chapter » Tasklisks",
"id": "15",
"title": "Tasklisks"
},
"16": {
"body": "Please be careful editing, this contains carefully crafted characters. Two byte character: spatiëring Combining character: spatiëring Three byte character: 书こんにちは Four byte character: 𐌀‮𐌁‮𐌂‮𐌃‮𐌄‮𐌅‮𐌆‮𐌇‮𐌈‬ Right-to-left: مرحبا Emoticons: 🔊 😍 💜 1⃣ right-to-left mark: hello באמת! Zalgo: ǫ̛̖̱̗̝͈̋͒͋̏ͥͫ̒̆ͩ̏͌̾͊͐ͪ̾̚",
"breadcrumbs": "First Chapter » Unicode » Unicode stress tests",
"breadcrumbs": "First Chapter » Unicode stress tests",
"id": "16",
"title": "Unicode stress tests"
},
"17": {
"body": "This makes sure you can insert runnable Rust files. fn main() { println!(\"Hello World!\");\n#\n# // You can even hide lines! :D\n# println!(\"I am hidden! Expand the code snippet to see me\");\n}",
"breadcrumbs": "Second Chapter » Second Chapter",
"breadcrumbs": "Second Chapter",
"id": "17",
"title": "Second Chapter"
},
"18": {
"body": "When we link to the first section , it should work on both the print page and the non-print page. A fragment link should work. Link outside . Some image HTML Link",
"breadcrumbs": "Second Chapter » Nested Chapter » Testing relative links for the print page",
"breadcrumbs": "Second Chapter » Testing relative links for the print page",
"id": "18",
"title": "Testing relative links for the print page"
},
"19": {
"body": "",
"breadcrumbs": "Second Chapter » Nested Chapter » Some section",
"breadcrumbs": "Second Chapter » Some section",
"id": "19",
"title": "Some section"
},
"2": {
"body": "more text.",
"breadcrumbs": "First Chapter » First Chapter",
"breadcrumbs": "First Chapter",
"id": "2",
"title": "First Chapter"
},
"20": {
"body": "I put &lt;HTML&gt; in here!",
"breadcrumbs": "Conclusion » Conclusion",
"breadcrumbs": "Conclusion",
"id": "20",
"title": "Conclusion"
},
"3": {
"body": "",
"breadcrumbs": "First Chapter » Some Section",
"breadcrumbs": "Some Section",
"id": "3",
"title": "Some Section"
},
"4": {
"body": "This file has some testable code. assert!(true);",
"breadcrumbs": "First Chapter » Nested Chapter » Nested Chapter",
"breadcrumbs": "First Chapter » Nested Chapter",
"id": "4",
"title": "Nested Chapter"
},
"5": {
"body": "assert!(true);",
"breadcrumbs": "First Chapter » Nested Chapter » Some Section",
"breadcrumbs": "First Chapter » Some Section",
"id": "5",
"title": "Some Section"
},
"6": {
"body": "// The next line will cause a `rendered_output` test to fail if the anchor feature is broken in\n// such a way that the content between anchors isn't included.\n// unique-string-for-anchor-test\nassert!(true);",
"breadcrumbs": "First Chapter » Nested Chapter » Anchors include the part of a file between special comments",
"breadcrumbs": "First Chapter » Anchors include the part of a file between special comments",
"id": "6",
"title": "Anchors include the part of a file between special comments"
},
"7": {
"body": "# fn some_function() {\n# assert!(true);\n# }\n# fn main() { some_function();\n}",
"breadcrumbs": "First Chapter » Nested Chapter » Rustdoc include adds the rest of the file as hidden",
"breadcrumbs": "First Chapter » Rustdoc include adds the rest of the file as hidden",
"id": "7",
"title": "Rustdoc include adds the rest of the file as hidden"
},
"8": {
"body": "# fn some_other_function() {\n# assert!(true);\n# }\n# fn main() { some_other_function();\n}",
"breadcrumbs": "First Chapter » Nested Chapter » Rustdoc include works with anchors too",
"breadcrumbs": "First Chapter » Rustdoc include works with anchors too",
"id": "8",
"title": "Rustdoc include works with anchors too"
},
"9": {
"body": "",
"breadcrumbs": "First Chapter » Includes » Includes",
"breadcrumbs": "First Chapter » Includes",
"id": "9",
"title": "Includes"
}
@@ -3048,7 +3048,7 @@
"df": 2,
"docs": {
"0": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
},
"10": {
"tf": 1.0
@@ -3222,7 +3222,7 @@
"df": 0,
"docs": {},
"r": {
"df": 18,
"df": 17,
"docs": {
"10": {
"tf": 2.23606797749979
@@ -3246,34 +3246,31 @@
"tf": 1.0
},
"17": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
},
"18": {
"tf": 1.4142135623730951
},
"19": {
"tf": 1.4142135623730951
},
"2": {
"tf": 1.7320508075688772
},
"3": {
"tf": 1.0
},
"19": {
"tf": 1.0
},
"2": {
"tf": 1.4142135623730951
},
"4": {
"tf": 2.0
"tf": 1.7320508075688772
},
"5": {
"tf": 1.4142135623730951
"tf": 1.0
},
"6": {
"tf": 1.4142135623730951
"tf": 1.0
},
"7": {
"tf": 1.4142135623730951
"tf": 1.0
},
"8": {
"tf": 1.4142135623730951
"tf": 1.0
},
"9": {
"tf": 1.0
@@ -3382,7 +3379,7 @@
"tf": 1.0
},
"20": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
}
}
}
@@ -3470,7 +3467,7 @@
"df": 2,
"docs": {
"0": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
},
"10": {
"tf": 1.0
@@ -3675,7 +3672,7 @@
"df": 0,
"docs": {},
"t": {
"df": 16,
"df": 15,
"docs": {
"10": {
"tf": 1.4142135623730951
@@ -3702,10 +3699,7 @@
"tf": 1.0
},
"2": {
"tf": 1.7320508075688772
},
"3": {
"tf": 1.0
"tf": 1.4142135623730951
},
"4": {
"tf": 1.0
@@ -3970,7 +3964,7 @@
"df": 5,
"docs": {
"10": {
"tf": 1.4142135623730951
"tf": 1.0
},
"6": {
"tf": 1.7320508075688772
@@ -3982,7 +3976,7 @@
"tf": 1.4142135623730951
},
"9": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
}
}
},
@@ -4071,7 +4065,7 @@
"df": 2,
"docs": {
"1": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
},
"10": {
"tf": 1.0
@@ -4288,25 +4282,13 @@
"df": 0,
"docs": {},
"n": {
"df": 6,
"df": 2,
"docs": {
"10": {
"tf": 1.0
},
"11": {
"tf": 2.0
},
"12": {
"tf": 1.0
},
"13": {
"tf": 1.0
},
"14": {
"tf": 1.0
},
"15": {
"tf": 1.0
"tf": 1.7320508075688772
}
}
}
@@ -4379,31 +4361,13 @@
"df": 0,
"docs": {},
"t": {
"df": 8,
"df": 2,
"docs": {
"10": {
"tf": 1.4142135623730951
},
"18": {
"tf": 1.0
},
"19": {
"tf": 1.0
},
"4": {
"tf": 1.7320508075688772
},
"5": {
"tf": 1.0
},
"6": {
"tf": 1.0
},
"7": {
"tf": 1.0
},
"8": {
"tf": 1.0
"tf": 1.4142135623730951
}
}
}
@@ -4879,7 +4843,7 @@
"tf": 1.0
},
"17": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
},
"18": {
"tf": 1.0
@@ -5421,7 +5385,7 @@
"tf": 1.0
},
"16": {
"tf": 1.7320508075688772
"tf": 1.4142135623730951
}
}
},