diff --git a/src/book/mod.rs b/src/book/mod.rs index 941682ee..38ffbc0b 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -11,8 +11,8 @@ mod summary; mod book; mod init; -pub use self::book::{Book, BookItem, BookItems, Chapter}; -pub use self::summary::SectionNumber; +pub use self::book::{load_book, Book, BookItem, BookItems, Chapter}; +pub use self::summary::{parse_summary, Link, SectionNumber, Summary, SummaryItem}; pub use self::init::BookBuilder; use std::path::{Path, PathBuf}; diff --git a/src/book/summary.rs b/src/book/summary.rs index 8c1d5b05..63581c59 100644 --- a/src/book/summary.rs +++ b/src/book/summary.rs @@ -1,4 +1,4 @@ -use std::fmt::{self, Formatter, Display}; +use std::fmt::{self, Display, Formatter}; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use pulldown_cmark::{self, Event, Tag}; @@ -193,6 +193,7 @@ macro_rules! collect_events { loop { let event = $stream.next(); + trace!("Next event: {:?}", event); match event { Some(Event::End($delimiter)) => break, Some(other) => events.push(other), @@ -382,6 +383,7 @@ impl<'a> SummaryParser<'a> { /// Parse a single item (`[Some Chapter Name](./path/to/chapter.md)`). fn parse_item(&mut self) -> Result { let next = self.stream.next(); + trace!("Parsing an item, next event is {:?}", next); if let Some(Event::Start(Tag::Link(dest, _))) = next { let content = collect_events!(self.stream, Tag::Link(..)); @@ -580,7 +582,6 @@ mod tests { let got = stringify_events(events); assert_eq!(got, should_be); - } #[test] diff --git a/tests/summary_md_files/example_book.md b/tests/summary_md_files/example_book.md new file mode 100644 index 00000000..ff3911c7 --- /dev/null +++ b/tests/summary_md_files/example_book.md @@ -0,0 +1,20 @@ +# Summary + +- [mdBook](README.md) +- [Command Line Tool](cli/cli-tool.md) + - [init](cli/init.md) + - [build](cli/build.md) + - [watch](cli/watch.md) + - [serve](cli/serve.md) + - [test](cli/test.md) +- [Format](format/format.md) + - [SUMMARY.md](format/summary.md) + - [Configuration](format/config.md) + - [Theme](format/theme/theme.md) + - [index.hbs](format/theme/index-hbs.md) + - [Syntax highlighting](format/theme/syntax-highlighting.md) + - [MathJax Support](format/mathjax.md) + - [Rust code specific features](format/rust.md) +- [Rust Library](lib/lib.md) +----------- +[Contributors](misc/contributors.md) diff --git a/tests/summary_md_files/rust_by_example.md b/tests/summary_md_files/rust_by_example.md new file mode 100644 index 00000000..de7e6f6e --- /dev/null +++ b/tests/summary_md_files/rust_by_example.md @@ -0,0 +1,191 @@ +# Summary + +[Introduction](index.md) + +- [Hello World](hello.md) + - [Comments](hello/comment.md) + - [Formatted print](hello/print.md) + - [Debug](hello/print/print_debug.md) + - [Display](hello/print/print_display.md) + - [Testcase: List](hello/print/print_display/testcase_list.md) + - [Formatting](hello/print/fmt.md) + +- [Primitives](primitives.md) + - [Literals and operators](primitives/literals.md) + - [Tuples](primitives/tuples.md) + - [Arrays and Slices](primitives/array.md) + +- [Custom Types](custom_types.md) + - [Structures](custom_types/structs.md) + - [Enums](custom_types/enum.md) + - [use](custom_types/enum/enum_use.md) + - [C-like](custom_types/enum/c_like.md) + - [Testcase: linked-list](custom_types/enum/testcase_linked_list.md) + - [constants](custom_types/constants.md) + +- [Variable Bindings](variable_bindings.md) + - [Mutability](variable_bindings/mut.md) + - [Scope and Shadowing](variable_bindings/scope.md) + - [Declare first](variable_bindings/declare.md) + +- [Types](types.md) + - [Casting](types/cast.md) + - [Literals](types/literals.md) + - [Inference](types/inference.md) + - [Aliasing](types/alias.md) + +- [Conversion](conversion.md) + - [From and Into](conversion/from_into.md) + - [To and From String](conversion/string.md) + +- [Expressions](expression.md) + +- [Flow Control](flow_control.md) + - [if/else](flow_control/if_else.md) + - [loop](flow_control/loop.md) + - [Nesting and labels](flow_control/loop/nested.md) + - [Returning from loops](flow_control/loop/return.md) + - [while](flow_control/while.md) + - [for and range](flow_control/for.md) + - [match](flow_control/match.md) + - [Destructuring](flow_control/match/destructuring.md) + - [tuples](flow_control/match/destructuring/destructure_tuple.md) + - [enums](flow_control/match/destructuring/destructure_enum.md) + - [pointers/ref](flow_control/match/destructuring/destructure_pointers.md) + - [structs](flow_control/match/destructuring/destructure_structures.md) + - [Guards](flow_control/match/guard.md) + - [Binding](flow_control/match/binding.md) + - [if let](flow_control/if_let.md) + - [while let](flow_control/while_let.md) + +- [Functions](fn.md) + - [Methods](fn/methods.md) + - [Closures](fn/closures.md) + - [Capturing](fn/closures/capture.md) + - [As input parameters](fn/closures/input_parameters.md) + - [Type anonymity](fn/closures/anonymity.md) + - [Input functions](fn/closures/input_functions.md) + - [As output parameters](fn/closures/output_parameters.md) + - [Examples in `std`](fn/closures/closure_examples.md) + - [Iterator::any](fn/closures/closure_examples/iter_any.md) + - [Iterator::find](fn/closures/closure_examples/iter_find.md) + - [Higher Order Functions](fn/hof.md) + +- [Modules](mod.md) + - [Visibility](mod/visibility.md) + - [Struct visibility](mod/struct_visibility.md) + - [The `use` declaration](mod/use.md) + - [`super` and `self`](mod/super.md) + - [File hierarchy](mod/split.md) + +- [Crates](crates.md) + - [Library](crates/lib.md) + - [`extern crate`](crates/link.md) + +- [Attributes](attribute.md) + - [`dead_code`](attribute/unused.md) + - [Crates](attribute/crate.md) + - [`cfg`](attribute/cfg.md) + - [Custom](attribute/cfg/custom.md) + +- [Generics](generics.md) + - [Functions](generics/gen_fn.md) + - [Implementation](generics/impl.md) + - [Traits](generics/gen_trait.md) + - [Bounds](generics/bounds.md) + - [Testcase: empty bounds](generics/bounds/testcase_empty.md) + - [Multiple bounds](generics/multi_bounds.md) + - [Where clauses](generics/where.md) + - [New Type Idiom](generics/new_types.md) + - [Associated items](generics/assoc_items.md) + - [The Problem](generics/assoc_items/the_problem.md) + - [Associated types](generics/assoc_items/types.md) + - [Phantom type parameters](generics/phantom.md) + - [Testcase: unit clarification](generics/phantom/testcase_units.md) + +- [Scoping rules](scope.md) + - [RAII](scope/raii.md) + - [Ownership and moves](scope/move.md) + - [Mutability](scope/move/mut.md) + - [Borrowing](scope/borrow.md) + - [Mutability](scope/borrow/mut.md) + - [Freezing](scope/borrow/freeze.md) + - [Aliasing](scope/borrow/alias.md) + - [The ref pattern](scope/borrow/ref.md) + - [Lifetimes](scope/lifetime.md) + - [Explicit annotation](scope/lifetime/explicit.md) + - [Functions](scope/lifetime/fn.md) + - [Methods](scope/lifetime/methods.md) + - [Structs](scope/lifetime/struct.md) + - [Bounds](scope/lifetime/lifetime_bounds.md) + - [Coercion](scope/lifetime/lifetime_coercion.md) + - [static](scope/lifetime/static_lifetime.md) + - [elision](scope/lifetime/elision.md) + +- [Traits](trait.md) + - [Derive](trait/derive.md) + - [Operator Overloading](trait/ops.md) + - [Drop](trait/drop.md) + - [Iterators](trait/iter.md) + - [Clone](trait/clone.md) + +- [macro_rules!](macros.md) + - [Syntax](macro/syntax.md) + - [Designators](macros/designators.md) + - [Overload](macros/overload.md) + - [Repeat](macros/repeat.md) + - [DRY (Don't Repeat Yourself)](macros/dry.md) + - [DSL (Domain Specific Languages)](macros/dsl.md) + - [Variadics](macros/variadics.md) + +- [Error handling](error.md) + - [`panic`](error/panic.md) + - [`Option` & `unwrap`](error/option_unwrap.md) + - [Combinators: `map`](error/option_unwrap/map.md) + - [Combinators: `and_then`](error/option_unwrap/and_then.md) + - [`Result`](error/result.md) + - [`map` for `Result`](error/result/result_map.md) + - [aliases for `Result`](error/result/result_alias.md) + - [Early returns](error/result/early_returns.md) + - [Introducing `?`](error/result/enter_question_mark.md) + - [Multiple error types](error/multiple_error_types.md) + - [Pulling `Result`s out of `Option`s](error/multiple_error_types/option_result.md) + - [Defining an error type](error/multiple_error_types/define_error_type.md) + - [`Box`ing errors](error/multiple_error_types/boxing_errors.md) + - [Other uses of `?`](error/multiple_error_types/reenter_question_mark.md) + - [Wrapping errors](error/multiple_error_types/wrap_error.md) + - [Iterating over `Result`s](error/iter_result.md) + +- [Std library types](std.md) + - [Box, stack and heap](std/box.md) + - [Vectors](std/vec.md) + - [Strings](std/str.md) + - [`Option`](std/option.md) + - [`Result`](std/result.md) + - [`?`](std/result/question_mark.md) + - [`panic!`](std/panic.md) + - [HashMap](std/hash.md) + - [Alternate/custom key types](std/hash/alt_key_types.md) + - [HashSet](std/hash/hashset.md) + +- [Std misc](std_misc.md) + - [Threads](std_misc/threads.md) + - [Testcase: map-reduce](std_misc/threads/testcase_mapreduce.md) + - [Channels](std_misc/channels.md) + - [Path](std_misc/path.md) + - [File I/O](std_misc/file.md) + - [`open`](std_misc/file/open.md) + - [`create`](std_misc/file/create.md) + - [Child processes](std_misc/process.md) + - [Pipes](std_misc/process/pipe.md) + - [Wait](std_misc/process/wait.md) + - [Filesystem Operations](std_misc/fs.md) + - [Program arguments](std_misc/arg.md) + - [Argument parsing](std_misc/arg/matching.md) + - [Foreign Function Interface](std_misc/ffi.md) + +- [Meta](meta.md) + - [Documentation](meta/doc.md) + - [Testing](meta/test.md) + +- [Unsafe Operations](unsafe.md) diff --git a/tests/summary_md_files/rust_ffi_guide.md b/tests/summary_md_files/rust_ffi_guide.md new file mode 100644 index 00000000..f64fcab1 --- /dev/null +++ b/tests/summary_md_files/rust_ffi_guide.md @@ -0,0 +1,19 @@ +# Summary + +- [Overview](./overview.md) +- [Setting Up](./setting_up.md) +- [Core Client Library](./client.md) +- [Constructing a Basic Request](./basic_request.md) +- [Sending the Request](./send_basic.md) +- [Generating a Header File](./cbindgen.md) +- [Better Error Handling](./error_handling.md) +- [Asynchronous Operations](./async.md) +- [More Complex Requests](./complex_request.md) +- [Testing](./testing.md) +- [Dynamic Loading & Plugins](./dynamic_loading.md) + +--- + +- [Break All The Things!!1!](./fun/index.md) + - [Problems](./fun/problems.md) + - [Solutions](./fun/solutions.md) \ No newline at end of file diff --git a/tests/summary_parser.rs b/tests/summary_parser.rs new file mode 100644 index 00000000..730d4204 --- /dev/null +++ b/tests/summary_parser.rs @@ -0,0 +1,48 @@ +//! Some integration tests to make sure the `SUMMARY.md` parser can deal with +//! some real-life examples. + +extern crate error_chain; +extern crate env_logger; +extern crate mdbook; + +use std::fs::File; +use std::io::Read; +use std::path::Path; +use mdbook::book; + +macro_rules! summary_md_test { + ($name:ident, $filename:expr) => { + #[test] + fn $name() { + env_logger::init().ok(); + + let filename = Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests") + .join("summary_md_files") + .join($filename); + + if !filename.exists() { + panic!("{} Doesn't exist", filename.display()); + } + + let mut content = String::new(); + File::open(&filename) + .unwrap() + .read_to_string(&mut content) + .unwrap(); + + if let Err(e) = book::parse_summary(&content) { + use error_chain::ChainedError; + + eprintln!("Error parsing {}:", filename.display()); + eprintln!(); + eprintln!("{}", e.display_chain()); + panic!(); + } + } + }; +} + +summary_md_test!(rust_by_example, "rust_by_example.md"); +summary_md_test!(rust_ffi_guide, "rust_ffi_guide.md"); +summary_md_test!(example_book, "example_book.md");