Merge remote-tracking branch 'origin/book-struct' into ebooks
This commit is contained in:
commit
44b03bd628
|
@ -1,5 +1,7 @@
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](misc/introduction.md)
|
||||||
|
|
||||||
- [mdBook](README.md)
|
- [mdBook](README.md)
|
||||||
- [Command Line Tool](cli/cli-tool.md)
|
- [Command Line Tool](cli/cli-tool.md)
|
||||||
- [init](cli/init.md)
|
- [init](cli/init.md)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
A frontmatter chapter.
|
|
@ -0,0 +1,80 @@
|
||||||
|
use book::metadata::BookMetadata;
|
||||||
|
use book::chapter::Chapter;
|
||||||
|
|
||||||
|
|
||||||
|
/// The `Book` struct contains the metadata and chapters for one language of the book.
|
||||||
|
/// Multiple `Book` structs are combined in the `MDBook` struct to support multi-language books.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Book {
|
||||||
|
metadata: BookMetadata,
|
||||||
|
|
||||||
|
frontmatter: Vec<Chapter>,
|
||||||
|
mainmatter: Vec<Chapter>,
|
||||||
|
backmatter: Vec<Chapter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Book {
|
||||||
|
/// Creates a new book with the given title, chapters are added with the
|
||||||
|
/// `add_frontmatter_chapter`, `add_mainmatter_chapter`,
|
||||||
|
/// `add_backmatter_chapter` methods
|
||||||
|
pub fn new(title: &str) -> Self {
|
||||||
|
Book {
|
||||||
|
metadata: BookMetadata::new(title),
|
||||||
|
|
||||||
|
frontmatter: Vec::new(),
|
||||||
|
mainmatter: Vec::new(),
|
||||||
|
backmatter: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a new mainmatter chapter
|
||||||
|
pub fn add_mainmatter_chapter(&mut self, chapter: Chapter) -> &mut Self {
|
||||||
|
self.mainmatter.push(chapter);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a new frontmatter chapter
|
||||||
|
pub fn add_frontmatter_chapter(&mut self, chapter: Chapter) -> &mut Self {
|
||||||
|
self.frontmatter.push(chapter);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a new backmatter chapter
|
||||||
|
pub fn add_backmatter_chapter(&mut self, chapter: Chapter) -> &mut Self {
|
||||||
|
self.backmatter.push(chapter);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// This method takes a slice `&[x, y, z]` as parameter and returns the corresponding chapter.
|
||||||
|
/// For example, to retrieve chapter 2.3 we would use:
|
||||||
|
/// ```
|
||||||
|
/// #extern crate mdbook;
|
||||||
|
/// #use mdbook::book::Book;
|
||||||
|
/// #fn main() {
|
||||||
|
/// #let book = Book::new("Test");
|
||||||
|
/// let chapter_2_3 = book.get_chapter(&[2, 3]);
|
||||||
|
/// #}
|
||||||
|
/// ```
|
||||||
|
pub fn get_chapter(&self, section: &[usize]) -> Option<&Chapter> {
|
||||||
|
match section.len() {
|
||||||
|
0 => None,
|
||||||
|
1 => self.mainmatter.get(section[0]),
|
||||||
|
_ => {
|
||||||
|
self.mainmatter
|
||||||
|
.get(section[0])
|
||||||
|
.and_then(|ch| ch.get_sub_chapter(§ion[1..]))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the metadata for modification
|
||||||
|
pub fn mut_metadata(&mut self) -> &mut BookMetadata {
|
||||||
|
&mut self.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a reference to the metadata
|
||||||
|
pub fn metadata(&self) -> &BookMetadata {
|
||||||
|
&self.metadata
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use book::metadata::Author;
|
||||||
|
|
||||||
|
/// The Chapter struct holds the title of the chapter as written in the SUMMARY.md file,
|
||||||
|
/// the location of the markdown file containing the content and eventually sub-chapters
|
||||||
|
|
||||||
|
/// TODO use in template: author, description, index, class
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Chapter {
|
||||||
|
/// The title of the chapter.
|
||||||
|
title: String,
|
||||||
|
/// Path to chapter's markdown file.
|
||||||
|
file: PathBuf,
|
||||||
|
|
||||||
|
/// TODO The author of the chapter, or the book.
|
||||||
|
author: Author,
|
||||||
|
/// TODO The description of the chapter.
|
||||||
|
description: String,
|
||||||
|
/// TODO Index number of the chapter in its level. This is the Vec index + 1.
|
||||||
|
index: i32,
|
||||||
|
/// TODO CSS class that will be added to the page-level wrap div to allow customized chapter styles.
|
||||||
|
class: String,
|
||||||
|
|
||||||
|
sub_chapters: Vec<Chapter>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chapter {
|
||||||
|
/// Creates a new chapter with the given title and source file and no sub-chapters
|
||||||
|
pub fn new(title: &str, file: &Path) -> Self {
|
||||||
|
Chapter {
|
||||||
|
title: title.to_owned(),
|
||||||
|
file: file.to_owned(),
|
||||||
|
|
||||||
|
sub_chapters: Vec::new(),
|
||||||
|
|
||||||
|
// TODO placeholder values for now
|
||||||
|
author: Author::new(""),
|
||||||
|
description: "".to_string(),
|
||||||
|
index: 0,
|
||||||
|
class: "".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function takes a slice `&[x,y,z]` and returns the corresponding sub-chapter if it exists.
|
||||||
|
///
|
||||||
|
/// For example: `chapter.get_sub_chapter(&[1,3])` will return the third sub-chapter of the first sub-chapter.
|
||||||
|
pub fn get_sub_chapter(&self, section: &[usize]) -> Option<&Chapter> {
|
||||||
|
match section.len() {
|
||||||
|
0 => None,
|
||||||
|
1 => self.sub_chapters.get(section[0]),
|
||||||
|
_ => {
|
||||||
|
// The lengt of the slice is more than one, this means that we want a sub-chapter of a sub-chapter
|
||||||
|
// We call `get_sub_chapter` recursively until we are deep enough and return the asked sub-chapter
|
||||||
|
self.sub_chapters
|
||||||
|
.get(section[0])
|
||||||
|
.and_then(|ch| ch.get_sub_chapter(§ion[1..]))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn title(&self) -> &str {
|
||||||
|
&self.title
|
||||||
|
}
|
||||||
|
pub fn file(&self) -> &Path {
|
||||||
|
&self.file
|
||||||
|
}
|
||||||
|
pub fn sub_chapters(&self) -> &[Chapter] {
|
||||||
|
&self.sub_chapters
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
/// TODO use in template: subtitle, description, publisher, number_format, section_names
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BookMetadata {
|
||||||
|
/// The title of the book.
|
||||||
|
pub title: String,
|
||||||
|
|
||||||
|
/// TODO The subtitle, when titles are in the form of "The Immense Journey: An
|
||||||
|
/// Imaginative Naturalist Explores the Mysteries of Man and Nature"
|
||||||
|
pub subtitle: String,
|
||||||
|
|
||||||
|
/// TODO A brief description or summary.
|
||||||
|
pub description: String,
|
||||||
|
|
||||||
|
/// TODO Publisher's info
|
||||||
|
pub publisher: Publisher,
|
||||||
|
|
||||||
|
pub language: Language,
|
||||||
|
|
||||||
|
authors: Vec<Author>,
|
||||||
|
translators: Vec<Author>,
|
||||||
|
|
||||||
|
/// TODO Chapter numbering scheme
|
||||||
|
number_format: NumberFormat,
|
||||||
|
/// TODO Section names for nested Vec<Chapter> structures, such as `[
|
||||||
|
/// "Part", "Chapter", "Section" ]`
|
||||||
|
section_names: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Author {
|
||||||
|
name: String,
|
||||||
|
email: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Language {
|
||||||
|
name: String,
|
||||||
|
code: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO use Publisher in template.
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Publisher {
|
||||||
|
name: String,
|
||||||
|
/// link to the sublisher's site
|
||||||
|
url: String,
|
||||||
|
/// path to publisher's logo image
|
||||||
|
logo_src: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Publisher {
|
||||||
|
pub fn default() -> Publisher {
|
||||||
|
Publisher {
|
||||||
|
name: "".to_string(),
|
||||||
|
url: "".to_string(),
|
||||||
|
logo_src: PathBuf::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO use NumberFormat when rendering chapter titles.
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum NumberFormat {
|
||||||
|
/// 19
|
||||||
|
Arabic,
|
||||||
|
/// XIX
|
||||||
|
Roman,
|
||||||
|
/// Nineteen
|
||||||
|
Word,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BookMetadata {
|
||||||
|
pub fn new(title: &str) -> Self {
|
||||||
|
BookMetadata {
|
||||||
|
title: title.to_owned(),
|
||||||
|
description: String::new(),
|
||||||
|
|
||||||
|
language: Language::default(),
|
||||||
|
|
||||||
|
authors: Vec::new(),
|
||||||
|
translators: Vec::new(),
|
||||||
|
|
||||||
|
// TODO placeholder values for now
|
||||||
|
subtitle: "".to_string(),
|
||||||
|
publisher: Publisher::default(),
|
||||||
|
number_format: NumberFormat::Arabic,
|
||||||
|
section_names: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_description(&mut self, description: &str) -> &mut Self {
|
||||||
|
self.description = description.to_owned();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_author(&mut self, author: Author) -> &mut Self {
|
||||||
|
self.authors.push(author);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Author {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Author {
|
||||||
|
name: name.to_owned(),
|
||||||
|
email: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_email(mut self, email: &str) -> Self {
|
||||||
|
self.email = Some(email.to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Default for Language {
|
||||||
|
fn default() -> Self {
|
||||||
|
Language {
|
||||||
|
name: String::from("English"),
|
||||||
|
code: String::from("en"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,12 @@
|
||||||
pub mod bookitem;
|
pub mod bookitem;
|
||||||
pub mod bookconfig;
|
pub mod bookconfig;
|
||||||
|
pub mod metadata;
|
||||||
|
pub mod chapter;
|
||||||
|
pub mod book;
|
||||||
|
|
||||||
|
pub use self::metadata::{Author, Language, BookMetadata};
|
||||||
|
pub use self::chapter::Chapter;
|
||||||
|
pub use self::book::Book;
|
||||||
|
|
||||||
pub use self::bookitem::{BookItem, BookItems};
|
pub use self::bookitem::{BookItem, BookItems};
|
||||||
pub use self::bookconfig::BookConfig;
|
pub use self::bookconfig::BookConfig;
|
||||||
|
@ -11,12 +18,13 @@ use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use {theme, parse, utils};
|
use {theme, parse, utils};
|
||||||
use renderer::{Renderer, HtmlHandlebars};
|
use renderer::{Renderer, HtmlHandlebars};
|
||||||
|
|
||||||
|
|
||||||
pub struct MDBook {
|
pub struct MDBook<'a> {
|
||||||
root: PathBuf,
|
root: PathBuf,
|
||||||
dest: PathBuf,
|
dest: PathBuf,
|
||||||
src: PathBuf,
|
src: PathBuf,
|
||||||
|
@ -27,12 +35,13 @@ pub struct MDBook {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
|
|
||||||
pub content: Vec<BookItem>,
|
pub content: Vec<BookItem>,
|
||||||
|
books: HashMap<&'a str, Book>,
|
||||||
renderer: Box<Renderer>,
|
renderer: Box<Renderer>,
|
||||||
|
|
||||||
livereload: Option<String>,
|
livereload: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MDBook {
|
impl<'a> MDBook<'a> {
|
||||||
/// Create a new `MDBook` struct with root directory `root`
|
/// Create a new `MDBook` struct with root directory `root`
|
||||||
///
|
///
|
||||||
/// Default directory paths:
|
/// Default directory paths:
|
||||||
|
@ -60,6 +69,7 @@ impl MDBook {
|
||||||
description: String::new(),
|
description: String::new(),
|
||||||
|
|
||||||
content: vec![],
|
content: vec![],
|
||||||
|
books: HashMap::new(),
|
||||||
renderer: Box::new(HtmlHandlebars::new()),
|
renderer: Box::new(HtmlHandlebars::new()),
|
||||||
|
|
||||||
livereload: None,
|
livereload: None,
|
||||||
|
|
Loading…
Reference in New Issue