Make mdbook init
output multilingual structure
This commit is contained in:
parent
5e223e074e
commit
a042cfc72b
@ -3,7 +3,7 @@ use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::MDBook;
|
||||
use crate::config::Config;
|
||||
use crate::config::{Config, Language};
|
||||
use crate::errors::*;
|
||||
use crate::theme;
|
||||
|
||||
@ -14,22 +14,46 @@ pub struct BookBuilder {
|
||||
create_gitignore: bool,
|
||||
config: Config,
|
||||
copy_theme: bool,
|
||||
language_ident: String
|
||||
}
|
||||
|
||||
fn add_default_language(cfg: &mut Config, language_ident: String) {
|
||||
let language = Language {
|
||||
name: String::from("English"),
|
||||
default: true,
|
||||
title: None,
|
||||
authors: None,
|
||||
description: None,
|
||||
};
|
||||
cfg.language.0.insert(language_ident, language);
|
||||
}
|
||||
|
||||
impl BookBuilder {
|
||||
/// Create a new `BookBuilder` which will generate a book in the provided
|
||||
/// root directory.
|
||||
pub fn new<P: Into<PathBuf>>(root: P) -> BookBuilder {
|
||||
let language_ident = String::from("en");
|
||||
let mut cfg = Config::default();
|
||||
add_default_language(&mut cfg, language_ident.clone());
|
||||
|
||||
BookBuilder {
|
||||
root: root.into(),
|
||||
create_gitignore: false,
|
||||
config: Config::default(),
|
||||
config: cfg,
|
||||
copy_theme: false,
|
||||
language_ident: language_ident
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the [`Config`] to be used.
|
||||
pub fn with_config(&mut self, cfg: Config) -> &mut BookBuilder {
|
||||
/// Get the output source directory of the builder.
|
||||
pub fn source_dir(&self) -> PathBuf {
|
||||
let src = self.config.get_localized_src_path(Some(&self.language_ident)).unwrap();
|
||||
self.root.join(src)
|
||||
}
|
||||
|
||||
/// Set the `Config` to be used.
|
||||
pub fn with_config(&mut self, mut cfg: Config) -> &mut BookBuilder {
|
||||
add_default_language(&mut cfg, self.language_ident.clone());
|
||||
self.config = cfg;
|
||||
self
|
||||
}
|
||||
@ -101,8 +125,8 @@ impl BookBuilder {
|
||||
|
||||
File::create(book_toml)
|
||||
.with_context(|| "Couldn't create book.toml")?
|
||||
.write_all(&cfg)
|
||||
.with_context(|| "Unable to write config to book.toml")?;
|
||||
.write_all(&cfg)
|
||||
.with_context(|| "Unable to write config to book.toml")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -172,7 +196,7 @@ impl BookBuilder {
|
||||
|
||||
fn create_stub_files(&self) -> Result<()> {
|
||||
debug!("Creating example book contents");
|
||||
let src_dir = self.root.join(&self.config.book.src);
|
||||
let src_dir = self.source_dir();
|
||||
|
||||
let summary = src_dir.join("SUMMARY.md");
|
||||
if !summary.exists() {
|
||||
@ -193,10 +217,10 @@ impl BookBuilder {
|
||||
}
|
||||
|
||||
fn create_directory_structure(&self) -> Result<()> {
|
||||
debug!("Creating directory tree");
|
||||
debug!("Creating directory tree at {}", self.root.display());
|
||||
fs::create_dir_all(&self.root)?;
|
||||
|
||||
let src = self.root.join(&self.config.book.src);
|
||||
let src = self.source_dir();
|
||||
fs::create_dir_all(&src)?;
|
||||
|
||||
let build = self.root.join(&self.config.build.build_dir);
|
||||
|
@ -84,7 +84,7 @@ pub fn execute(args: &ArgMatches) -> Result<()> {
|
||||
}
|
||||
|
||||
builder.build()?;
|
||||
println!("\nAll done, no errors...");
|
||||
println!("\nCreated new book at {}", builder.source_dir().display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -197,8 +197,8 @@ async fn serve(
|
||||
warp::path::end().map(move || warp::redirect(index_for_language.clone()));
|
||||
|
||||
// BUG: It is not possible to conditionally redirect to the correct 404
|
||||
// page depending on the URL in warp, so just redirect to the one in the
|
||||
// default language.
|
||||
// page depending on the URL using warp, so just redirect to the one in
|
||||
// the default language.
|
||||
// See: https://github.com/seanmonstar/warp/issues/171
|
||||
let fallback_route = warp::fs::file(build_dir.join(lang_ident).join(file_404))
|
||||
.map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND));
|
||||
|
@ -259,8 +259,8 @@ impl Config {
|
||||
// Languages have been specified, assume directory structure with
|
||||
// language subfolders.
|
||||
Some(ref default) => match index {
|
||||
// Make sure that the language we passed was actually
|
||||
// declared in the config, and return `None` if not.
|
||||
// Make sure that the language we passed was actually declared
|
||||
// in the config, and return an `Err` if not.
|
||||
Some(lang_ident) => match self.language.0.get(lang_ident.as_ref()) {
|
||||
Some(_) => Ok(Some(lang_ident.as_ref().into())),
|
||||
None => Err(anyhow!(
|
||||
@ -272,7 +272,7 @@ impl Config {
|
||||
None => Ok(Some(default.to_string())),
|
||||
},
|
||||
|
||||
// No default language was configured in book.toml.
|
||||
// No [language] table was declared in book.toml.
|
||||
None => match index {
|
||||
// We passed in a language from the frontend, but the config
|
||||
// offers no languages.
|
||||
@ -298,8 +298,8 @@ impl Config {
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
// No default language was configured in book.toml. Preserve
|
||||
// backwards compatibility by just returning `src`.
|
||||
// No [language] table was declared in book.toml. Preserve backwards
|
||||
// compatibility by just returning `src`.
|
||||
None => Ok(self.book.src.clone()),
|
||||
}
|
||||
}
|
||||
@ -491,6 +491,11 @@ impl Serialize for Config {
|
||||
table.insert("rust", rust_config);
|
||||
}
|
||||
|
||||
if !self.language.0.is_empty() {
|
||||
let language_config = Value::try_from(&self.language).expect("should always be serializable");
|
||||
table.insert("language", language_config);
|
||||
}
|
||||
|
||||
table.serialize(s)
|
||||
}
|
||||
}
|
||||
@ -551,7 +556,7 @@ impl Default for BookConfig {
|
||||
authors: Vec::new(),
|
||||
description: None,
|
||||
src: PathBuf::from("src"),
|
||||
multilingual: false,
|
||||
multilingual: true,
|
||||
language: Some(String::from("en")),
|
||||
}
|
||||
}
|
||||
|
@ -53,21 +53,22 @@ impl HtmlHandlebars {
|
||||
}
|
||||
}
|
||||
LoadedBook::Single(ref book) => {
|
||||
// `src_dir` points to the root source directory. If this book
|
||||
// is actually multilingual and we specified a single language
|
||||
// to build on the command line, then `src_dir` will not be
|
||||
// pointing at the subdirectory with the specified translation's
|
||||
// index/summary files. We have to append the language
|
||||
// identifier to prevent the files from the other translations
|
||||
// from being copied in the final step.
|
||||
let extra_file_dir = match &ctx.build_opts.language_ident {
|
||||
// `src_dir` points to the root source directory, not the
|
||||
// subdirectory with the translation's index/summary files.
|
||||
// We have to append the language identifier to prevent the
|
||||
// files from the other translations from being copied in
|
||||
// the final step.
|
||||
Some(lang_ident) => {
|
||||
let mut path = src_dir.clone();
|
||||
path.push(lang_ident);
|
||||
path
|
||||
}
|
||||
// `src_dir` is where index.html and the other extra files
|
||||
// are, so use that.
|
||||
None => src_dir.clone(),
|
||||
};
|
||||
|
||||
self.render_book(
|
||||
ctx,
|
||||
&book,
|
||||
|
@ -10,7 +10,7 @@ use tempfile::Builder as TempFileBuilder;
|
||||
/// are created.
|
||||
#[test]
|
||||
fn base_mdbook_init_should_create_default_content() {
|
||||
let created_files = vec!["book", "src", "src/SUMMARY.md", "src/chapter_1.md"];
|
||||
let created_files = vec!["book", "src", "src/en", "src/en/SUMMARY.md", "src/en/chapter_1.md"];
|
||||
|
||||
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
|
||||
for file in &created_files {
|
||||
@ -28,7 +28,7 @@ fn base_mdbook_init_should_create_default_content() {
|
||||
let contents = fs::read_to_string(temp.path().join("book.toml")).unwrap();
|
||||
assert_eq!(
|
||||
contents,
|
||||
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\n"
|
||||
"[book]\nauthors = []\nlanguage = \"en\"\nmultilingual = true\nsrc = \"src\"\n[language.en]\ndefault = true\nname = \"English\"\n"
|
||||
);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ fn run_mdbook_init_should_create_content_from_summary() {
|
||||
let created_files = vec!["intro.md", "first.md", "outro.md"];
|
||||
|
||||
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
|
||||
let src_dir = temp.path().join("src");
|
||||
let src_dir = temp.path().join("src").join("en");
|
||||
fs::create_dir_all(src_dir.clone()).unwrap();
|
||||
static SUMMARY: &str = r#"# Summary
|
||||
|
||||
@ -66,7 +66,7 @@ fn run_mdbook_init_should_create_content_from_summary() {
|
||||
/// files, then call `mdbook init`.
|
||||
#[test]
|
||||
fn run_mdbook_init_with_custom_book_and_src_locations() {
|
||||
let created_files = vec!["out", "in", "in/SUMMARY.md", "in/chapter_1.md"];
|
||||
let created_files = vec!["out", "in", "in/en", "in/en/SUMMARY.md", "in/en/chapter_1.md"];
|
||||
|
||||
let temp = TempFileBuilder::new().prefix("mdbook").tempdir().unwrap();
|
||||
for file in &created_files {
|
||||
|
Loading…
Reference in New Issue
Block a user