Allow for optional multiple shelves
This commit is contained in:
parent
2903f0711f
commit
3c58bf4132
104
src/cmd/shelf.rs
104
src/cmd/shelf.rs
|
@ -3,14 +3,14 @@ use std::io::Read;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use mdbook::config::BookshelfConfig;
|
||||||
use resolve_path::PathResolveExt;
|
use resolve_path::PathResolveExt;
|
||||||
|
|
||||||
use super::command_prelude::*;
|
use super::command_prelude::*;
|
||||||
use mdbook::config::ShelfConfig;
|
|
||||||
use mdbook::errors::Result;
|
use mdbook::errors::Result;
|
||||||
use mdbook::MDBook;
|
use mdbook::MDBook;
|
||||||
|
|
||||||
const SHELF_DIR: &str = "shelf";
|
const INDEX_BOOK_DIR: &str = "index";
|
||||||
const REPOS_DIR: &str = "repositories";
|
const REPOS_DIR: &str = "repositories";
|
||||||
const INDEX_MD_FILE: &str = "index.md";
|
const INDEX_MD_FILE: &str = "index.md";
|
||||||
const INDEX_HTML_FILE: &str = "index.html";
|
const INDEX_HTML_FILE: &str = "index.html";
|
||||||
|
@ -28,7 +28,7 @@ struct BookContext {
|
||||||
authors: String,
|
authors: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ShelfContext {
|
struct BookshelfContext {
|
||||||
book_dir: PathBuf,
|
book_dir: PathBuf,
|
||||||
source_dir: PathBuf,
|
source_dir: PathBuf,
|
||||||
url_prefix: String,
|
url_prefix: String,
|
||||||
|
@ -37,7 +37,7 @@ struct ShelfContext {
|
||||||
summary_file_name: PathBuf,
|
summary_file_name: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_index(
|
fn update_index_with_book(
|
||||||
index_file: &mut File,
|
index_file: &mut File,
|
||||||
summary_file: &mut File,
|
summary_file: &mut File,
|
||||||
shelf_source: &PathBuf,
|
shelf_source: &PathBuf,
|
||||||
|
@ -46,7 +46,7 @@ fn update_index(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Create post in index file
|
// Create post in index file
|
||||||
let book_link = format!(
|
let book_link = format!(
|
||||||
"## [{title}](<{prefix}/{BOOKSHELF_DIR}/{BOOKS_DIR}/{title}/{INDEX_HTML_FILE}>)",
|
"### [{title}](<{prefix}/{BOOKSHELF_DIR}/{BOOKS_DIR}/{title}/{INDEX_HTML_FILE}>)",
|
||||||
title = context.title,
|
title = context.title,
|
||||||
prefix = root_prefix
|
prefix = root_prefix
|
||||||
);
|
);
|
||||||
|
@ -73,7 +73,6 @@ fn update_index(
|
||||||
"- [{title}](./{file_name})",
|
"- [{title}](./{file_name})",
|
||||||
title = context.title
|
title = context.title
|
||||||
)?;
|
)?;
|
||||||
writeln!(summary_file)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -101,8 +100,8 @@ fn process_book(path: &str, books_dir: &PathBuf, shelf_url: &str) -> Result<Book
|
||||||
Ok(book_context)
|
Ok(book_context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_shelf_book(config: &ShelfConfig) -> Result<ShelfContext> {
|
fn setup_bookshelf_book(config: &BookshelfConfig) -> Result<BookshelfContext> {
|
||||||
let book_dir = format!("{BOOKSHELF_DIR}/{SHELF_DIR}");
|
let book_dir = format!("{BOOKSHELF_DIR}/{INDEX_BOOK_DIR}");
|
||||||
let book = MDBook::init(&book_dir).build()?;
|
let book = MDBook::init(&book_dir).build()?;
|
||||||
let build_dir = book.config.build.build_dir.to_str().unwrap_or_default();
|
let build_dir = book.config.build.build_dir.to_str().unwrap_or_default();
|
||||||
let url_prefix = if !config.root_url_prefix.is_empty() {
|
let url_prefix = if !config.root_url_prefix.is_empty() {
|
||||||
|
@ -120,7 +119,7 @@ fn setup_shelf_book(config: &ShelfConfig) -> Result<ShelfContext> {
|
||||||
let mut summary_file_name = book.source_dir();
|
let mut summary_file_name = book.source_dir();
|
||||||
summary_file_name.push(SUMMARY_MD_FILE);
|
summary_file_name.push(SUMMARY_MD_FILE);
|
||||||
|
|
||||||
Ok(ShelfContext {
|
Ok(BookshelfContext {
|
||||||
book_dir: book_dir.into(),
|
book_dir: book_dir.into(),
|
||||||
source_dir: book.source_dir(),
|
source_dir: book.source_dir(),
|
||||||
url_prefix,
|
url_prefix,
|
||||||
|
@ -131,51 +130,64 @@ fn setup_shelf_book(config: &ShelfConfig) -> Result<ShelfContext> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(_args: &ArgMatches) -> Result<()> {
|
pub fn execute(_args: &ArgMatches) -> Result<()> {
|
||||||
let mut file = File::open("shelf.toml")?;
|
// Make sure everything is clean
|
||||||
let mut contents = String::new();
|
|
||||||
file.read_to_string(&mut contents)?;
|
|
||||||
let shelf_config: ShelfConfig = toml::from_str(&contents)?;
|
|
||||||
|
|
||||||
let _ = std::fs::remove_dir_all(BOOKSHELF_DIR);
|
let _ = std::fs::remove_dir_all(BOOKSHELF_DIR);
|
||||||
let _ = std::fs::remove_dir_all(REPOS_DIR);
|
let _ = std::fs::remove_dir_all(REPOS_DIR);
|
||||||
|
|
||||||
let shelf_context = setup_shelf_book(&shelf_config)?;
|
let mut file = File::open("shelf.toml")?;
|
||||||
|
let mut contents = String::new();
|
||||||
|
file.read_to_string(&mut contents)?;
|
||||||
|
let bookshelf_config: BookshelfConfig = toml::from_str(&contents)?;
|
||||||
|
let shelf_context = setup_bookshelf_book(&bookshelf_config)?;
|
||||||
|
|
||||||
let mut index_file = File::create(shelf_context.index_file_name).unwrap();
|
let mut index_file = File::create(shelf_context.index_file_name).unwrap();
|
||||||
writeln!(index_file, "# {title}", title = shelf_config.title)?;
|
writeln!(index_file, "# {title}", title = bookshelf_config.title)?;
|
||||||
writeln!(index_file)?;
|
writeln!(index_file)?;
|
||||||
|
|
||||||
let mut summary_file = File::create(shelf_context.summary_file_name).unwrap();
|
let mut summary_file = File::create(shelf_context.summary_file_name).unwrap();
|
||||||
writeln!(summary_file, "# Summary")?;
|
writeln!(summary_file, "# Summary")?;
|
||||||
writeln!(
|
writeln!(
|
||||||
summary_file,
|
summary_file,
|
||||||
"- [{title}](./{INDEX_MD_FILE})",
|
"[{title}](./{INDEX_MD_FILE})",
|
||||||
title = shelf_config.title
|
title = bookshelf_config.title
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut books_build_dir = std::env::current_dir()?;
|
let mut books_build_dir = std::env::current_dir()?;
|
||||||
books_build_dir.push(BOOKSHELF_DIR);
|
books_build_dir.push(BOOKSHELF_DIR);
|
||||||
books_build_dir.push(BOOKS_DIR);
|
books_build_dir.push(BOOKS_DIR);
|
||||||
|
let books_build_dir = books_build_dir;
|
||||||
|
|
||||||
for sb in &shelf_config.books {
|
let shelves = if let Some(shelves) = bookshelf_config.shelves {
|
||||||
let book_path = if let Some(url) = &sb.git_url {
|
shelves
|
||||||
prepare_git(sb, url)
|
} else if let Some(shelf) = bookshelf_config.shelf_config {
|
||||||
} else if let Some(path) = &sb.path {
|
vec![shelf]
|
||||||
Some(path.to_owned())
|
} else {
|
||||||
} else {
|
error!("No shelves or default shelf found in config");
|
||||||
warn!("Neither path or git specified. Invalid book");
|
Vec::new()
|
||||||
None
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(path) = book_path {
|
for shelf_config in shelves {
|
||||||
let update_context = process_book(&path, &books_build_dir, &shelf_context.url)?;
|
let _ = start_shelf(&mut index_file, &mut summary_file, &shelf_config.title);
|
||||||
let _ = update_index(
|
for sb in &shelf_config.books {
|
||||||
&mut index_file,
|
let book_path = if let Some(url) = &sb.git_url {
|
||||||
&mut summary_file,
|
prepare_git(sb, url)
|
||||||
&shelf_context.source_dir,
|
} else if let Some(path) = &sb.path {
|
||||||
&shelf_context.url_prefix,
|
Some(path.to_owned())
|
||||||
update_context,
|
} else {
|
||||||
)?;
|
warn!("Neither path or git specified. Invalid book");
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(path) = book_path {
|
||||||
|
let update_context = process_book(&path, &books_build_dir, &shelf_context.url)?;
|
||||||
|
let _ = update_index_with_book(
|
||||||
|
&mut index_file,
|
||||||
|
&mut summary_file,
|
||||||
|
&shelf_context.source_dir,
|
||||||
|
&shelf_context.url_prefix,
|
||||||
|
update_context,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +197,14 @@ pub fn execute(_args: &ArgMatches) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_shelf(index_file: &mut File, summary_file: &mut File, title: &str) -> Result<()> {
|
||||||
|
writeln!(summary_file, "# {title}")?;
|
||||||
|
writeln!(summary_file)?;
|
||||||
|
|
||||||
|
writeln!(index_file, "## {title}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_git(sb: &mdbook::config::ShelfBook, url: &String) -> Option<String> {
|
fn prepare_git(sb: &mdbook::config::ShelfBook, url: &String) -> Option<String> {
|
||||||
println!("{:?}", sb);
|
println!("{:?}", sb);
|
||||||
|
|
||||||
|
@ -252,20 +272,20 @@ git_url = "secondurl"
|
||||||
[[book]]
|
[[book]]
|
||||||
path = "../test_book"
|
path = "../test_book"
|
||||||
"#;
|
"#;
|
||||||
let cfg: ShelfConfig = toml::from_str(&toml).unwrap();
|
let cfg: BookshelfConfig = toml::from_str(&toml).unwrap();
|
||||||
assert_eq!(cfg.root_url_prefix, "myprefix");
|
assert_eq!(cfg.root_url_prefix, "myprefix");
|
||||||
|
|
||||||
let book = &cfg.books[0];
|
let book = &cfg.shelf_config.clone().unwrap().books[0];
|
||||||
assert_eq!(book.git_url.clone().unwrap(), "firsturl");
|
assert_eq!(book.git_url.clone().unwrap(), "firsturl");
|
||||||
assert_eq!(book.git_ref.clone().unwrap(), "shelf");
|
assert_eq!(book.git_ref.clone().unwrap(), "shelf");
|
||||||
assert_eq!(book.path.clone().unwrap(), "guide");
|
assert_eq!(book.path.clone().unwrap(), "guide");
|
||||||
|
|
||||||
let book = &cfg.books[1];
|
let book = &cfg.shelf_config.clone().unwrap().books[1];
|
||||||
assert_eq!(book.git_url.clone().unwrap(), "secondurl");
|
assert_eq!(book.git_url.clone().unwrap(), "secondurl");
|
||||||
assert!(book.git_ref.is_none());
|
assert!(book.git_ref.is_none());
|
||||||
assert!(book.path.is_none());
|
assert!(book.path.is_none());
|
||||||
|
|
||||||
let book = &cfg.books[2];
|
let book = &cfg.shelf_config.clone().unwrap().books[2];
|
||||||
assert_eq!(book.path.clone().unwrap(), "../test_book");
|
assert_eq!(book.path.clone().unwrap(), "../test_book");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +295,7 @@ fn test_config_defaults() {
|
||||||
[[book]]
|
[[book]]
|
||||||
path = "../test_book"
|
path = "../test_book"
|
||||||
"#;
|
"#;
|
||||||
let cfg: ShelfConfig = toml::from_str(&toml).unwrap();
|
let cfg: BookshelfConfig = toml::from_str(&toml).unwrap();
|
||||||
assert_eq!(cfg.root_url_prefix, "".to_owned());
|
assert_eq!(cfg.root_url_prefix, "".to_owned());
|
||||||
assert_eq!(cfg.title, "Bookshelf".to_owned());
|
assert_eq!(cfg.title, "Overview".to_owned());
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,7 +637,7 @@ impl HtmlConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
/// Represents a book in a shelf
|
/// Represents a book in a shelf
|
||||||
pub struct ShelfBook {
|
pub struct ShelfBook {
|
||||||
/// Path to filesystem local book
|
/// Path to filesystem local book
|
||||||
|
@ -651,27 +651,44 @@ pub struct ShelfBook {
|
||||||
pub git_ref: Option<String>,
|
pub git_ref: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
/// Represents a shelf that contains a lot of books
|
/// Represents a shelf that contains a lot of books
|
||||||
pub struct ShelfConfig {
|
pub struct ShelfConfig {
|
||||||
/// The books in the shelf
|
/// The books in the shelf
|
||||||
#[serde(alias = "book")]
|
#[serde(alias = "book")]
|
||||||
pub books: Vec<ShelfBook>,
|
pub books: Vec<ShelfBook>,
|
||||||
|
/// Name of the shelf
|
||||||
|
#[serde(default = "default_shelf_title")]
|
||||||
|
pub title: String,
|
||||||
|
}
|
||||||
|
fn default_shelf_title() -> String {
|
||||||
|
"Bookshelf".to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
///
|
||||||
|
pub struct BookshelfConfig {
|
||||||
|
///
|
||||||
|
#[serde(alias = "shelf")]
|
||||||
|
pub shelves: Option<Vec<ShelfConfig>>,
|
||||||
|
///
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub shelf_config: Option<ShelfConfig>,
|
||||||
/// this will be prepeneded to the backreference url
|
/// this will be prepeneded to the backreference url
|
||||||
/// Say you want to publish to www.example.com/mydocs
|
/// Say you want to publish to www.example.com/mydocs
|
||||||
/// you would set this to "mydocs" and then find your bookshelf at
|
/// you would set this to "mydocs" and then find your bookshelf at
|
||||||
/// www.example.com/mydocs/bookshelf/shelf/book/index.html
|
/// www.example.com/mydocs/bookshelf/shelf/book/index.html
|
||||||
#[serde(default = "default_shelf_root_url")]
|
#[serde(default = "default_shelf_root_url")]
|
||||||
pub root_url_prefix: String,
|
pub root_url_prefix: String,
|
||||||
/// Name of the shelf
|
///
|
||||||
#[serde(default = "default_shelf_title")]
|
#[serde(default = "default_bookshelf_title")]
|
||||||
pub title: String,
|
pub title: String,
|
||||||
}
|
}
|
||||||
fn default_shelf_root_url() -> String {
|
fn default_shelf_root_url() -> String {
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
}
|
}
|
||||||
fn default_shelf_title() -> String {
|
fn default_bookshelf_title() -> String {
|
||||||
"Bookshelf".to_owned()
|
"Overview".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for how to render the print icon, print.html, and print.css.
|
/// Configuration for how to render the print icon, print.html, and print.css.
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
# Set this to your full path /<full_path>/test_shelf to be able to browse locally
|
||||||
|
# or any kind of prefix that you need for when you publish online
|
||||||
|
root_url_prefix = ""
|
||||||
|
|
||||||
|
# Use the first setup here for the simple one shelf structure
|
||||||
|
|
||||||
[[book]]
|
[[book]]
|
||||||
git_url = "https://github.com/Coi-l/mdBook.git"
|
git_url = "https://github.com/Coi-l/mdBook.git"
|
||||||
git_ref = "shelf"
|
git_ref = "shelf"
|
||||||
|
@ -8,3 +14,27 @@ git_url = "https://github.com/rust-lang/book.git"
|
||||||
|
|
||||||
[[book]]
|
[[book]]
|
||||||
path = "../test_book"
|
path = "../test_book"
|
||||||
|
|
||||||
|
##########################
|
||||||
|
##########################
|
||||||
|
##########################
|
||||||
|
# Uncomment the setup below to test the multishelf/category structure
|
||||||
|
|
||||||
|
|
||||||
|
# title = "Documentation"
|
||||||
|
|
||||||
|
# [[shelf]]
|
||||||
|
# title = "MdBook"
|
||||||
|
|
||||||
|
# [[shelf.book]]
|
||||||
|
# git_url = "https://github.com/Coi-l/mdBook.git"
|
||||||
|
# git_ref = "shelf"
|
||||||
|
# path = "guide"
|
||||||
|
|
||||||
|
# [[shelf.book]]
|
||||||
|
# path = "../test_book"
|
||||||
|
|
||||||
|
# [[shelf]]
|
||||||
|
# title = "Rust"
|
||||||
|
# [[shelf.book]]
|
||||||
|
# git_url = "https://github.com/rust-lang/book.git"
|
||||||
|
|
Loading…
Reference in New Issue