Add --drafts flag + rustfmt

This commit is contained in:
Vincent Prouillet 2019-08-24 22:23:08 +02:00
parent 57691be90d
commit b396a1bc20
20 changed files with 141 additions and 72 deletions

View File

@ -4,7 +4,7 @@
### Breaking
- Pages with draft=true are now only loaded/rendered in `zola serve`
- Add `--drafts` flag to `build`, `serve` and `check` to load drafts. Drafts are never loaded by default anymore
### Other
- Add `--open` flag to open server URL in default browser
@ -17,7 +17,7 @@
- Taxonomies can now have the same name in multiple languages
- `zola init` can now be create sites inside the current directory
- Fix table of contents generation for deep heading levels
- Add `lang` in all templates context except sitemap, robots etc
- Add `lang` in all templates context except sitemap, robots
- Add `lang` parameter to `get_taxonomy` and `get_taxonomy_url`
- Rebuild whole site on changes in `themes` changes
- Add one-dark syntax highlighting theme

8
Cargo.lock generated
View File

@ -249,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"html5ever 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tendril 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1334,7 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "maplit"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -1748,7 +1748,7 @@ name = "pest_meta"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -3375,7 +3375,7 @@ dependencies = [
"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
"checksum markup5ever 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "65381d9d47506b8592b97c4efd936afcf673b09b059f2bef39c7211ee78b9d03"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"

View File

@ -13,7 +13,7 @@ use theme::Theme;
use utils::fs::read_file_with_error;
// We want a default base url for tests
static DEFAULT_BASE_URL: &'static str = "http://a-website.com";
static DEFAULT_BASE_URL: &str = "http://a-website.com";
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum Mode {

View File

@ -24,7 +24,7 @@ pub struct PageFrontMatter {
/// The converted date into a (year, month, day) tuple
#[serde(default, skip_deserializing)]
pub datetime_tuple: Option<(i32, u32, u32)>,
/// Whether this page is a draft and should be ignored for pagination etc
/// Whether this page is a draft
pub draft: bool,
/// The page slug. Will be used instead of the filename if present
/// Can't be an empty string if present

View File

@ -7,7 +7,7 @@ use errors::Result;
use super::{InsertAnchor, SortBy};
static DEFAULT_PAGINATE_PATH: &'static str = "page";
static DEFAULT_PAGINATE_PATH: &str = "page";
/// The front matter of every section
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]

View File

@ -23,7 +23,7 @@ use regex::Regex;
use errors::{Error, Result};
use utils::fs as ufs;
static RESIZED_SUBDIR: &'static str = "processed_images";
static RESIZED_SUBDIR: &str = "processed_images";
lazy_static! {
pub static ref RESIZED_FILENAME: Regex =

View File

@ -117,9 +117,6 @@ impl<'a> Paginator<'a> {
for key in self.all_pages {
let page = library.get_page_by_key(*key);
if page.is_draft() {
continue;
}
current_page.push(page.to_serialized_basic(library));
if current_page.len() == self.paginate_by {
@ -283,7 +280,7 @@ mod tests {
assert_eq!(paginator.pagers[0].path, "posts/");
assert_eq!(paginator.pagers[1].index, 2);
assert_eq!(paginator.pagers[1].pages.len(), 1);
assert_eq!(paginator.pagers[1].pages.len(), 2);
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/posts/page/2/");
assert_eq!(paginator.pagers[1].path, "posts/page/2/");
}
@ -300,7 +297,7 @@ mod tests {
assert_eq!(paginator.pagers[0].path, "");
assert_eq!(paginator.pagers[1].index, 2);
assert_eq!(paginator.pagers[1].pages.len(), 1);
assert_eq!(paginator.pagers[1].pages.len(), 2);
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/page/2/");
assert_eq!(paginator.pagers[1].path, "page/2/");
}
@ -352,7 +349,7 @@ mod tests {
assert_eq!(paginator.pagers[0].path, "tags/something");
assert_eq!(paginator.pagers[1].index, 2);
assert_eq!(paginator.pagers[1].pages.len(), 1);
assert_eq!(paginator.pagers[1].pages.len(), 2);
assert_eq!(paginator.pagers[1].permalink, "https://vincent.is/tags/something/page/2/");
assert_eq!(paginator.pagers[1].path, "tags/something/page/2/");
}

View File

@ -317,7 +317,7 @@ pub fn markdown_to_html(content: &str, context: &RenderContext) -> Result<Render
}
if let Some(e) = error {
return Err(e);
Err(e)
} else {
Ok(Rendered {
summary_len: if has_summary { html.find(CONTINUE_READING) } else { None },

View File

@ -33,14 +33,14 @@ fn insert_into_parent(potential_parent: Option<&mut Header>, header: &Header) ->
match potential_parent {
None => {
// No potential parent to insert into so it needs to be insert higher
return false;
},
false
}
Some(parent) => {
let diff = header.level - parent.level;
if diff <= 0 {
// Heading is same level or higher so we don't insert here
return false;
}
}
if diff == 1 {
// We have a direct child of the parent
parent.children.push(header.clone());
@ -51,7 +51,7 @@ fn insert_into_parent(potential_parent: Option<&mut Header>, header: &Header) ->
// No, we need to insert it here
parent.children.push(header.clone());
}
return true;
true
}
}
}
@ -61,23 +61,9 @@ fn insert_into_parent(potential_parent: Option<&mut Header>, header: &Header) ->
pub fn make_table_of_contents(headers: Vec<Header>) -> Vec<Header> {
let mut toc = vec![];
for header in headers {
if toc.is_empty() {
// First header, nothing to compare it with
// First header or we try to insert the current header in a previous one
if toc.is_empty() || !insert_into_parent(toc.iter_mut().last(), &header) {
toc.push(header);
continue;
}
// We try to insert the current header in a previous one
match insert_into_parent(toc.iter_mut().last(), &header) {
true => {
// Header was successfully inserted as a child of a previous element
continue;
},
false => {
// Couldn't insert in a previous header, so it's a top-level header
toc.push(header);
continue;
}
}
}

View File

@ -63,6 +63,8 @@ pub struct Site {
pub permalinks: HashMap<String, String>,
/// Contains all pages and sections of the site
pub library: Arc<RwLock<Library>>,
/// Whether to load draft pages
include_drafts: bool,
}
impl Site {
@ -131,6 +133,7 @@ impl Site {
static_path,
taxonomies: Vec::new(),
permalinks: HashMap::new(),
include_drafts: false,
// We will allocate it properly later on
library: Arc::new(RwLock::new(Library::new(0, 0, false))),
};
@ -138,6 +141,12 @@ impl Site {
Ok(site)
}
/// Set the site to load the drafts.
/// Needs to be called before loading it
pub fn include_drafts(&mut self) {
self.include_drafts = true;
}
/// The index sections are ALWAYS at those paths
/// There are one index section for the basic language + 1 per language
fn index_section_paths(&self) -> Vec<(PathBuf, Option<String>)> {
@ -233,8 +242,8 @@ impl Site {
let mut pages_insert_anchors = HashMap::new();
for page in pages {
let p = page?;
// Draft pages are not rendered in zola build so we just discard them
if p.meta.draft && !self.config.is_in_serve_mode() {
// Should draft pages be ignored?
if p.meta.draft && !self.include_drafts {
continue;
}
pages_insert_anchors.insert(
@ -525,7 +534,7 @@ impl Site {
self.tera.register_function("trans", global_fns::Trans::new(self.config.clone()));
self.tera.register_function(
"get_taxonomy_url",
global_fns::GetTaxonomyUrl::new(&self.config.default_language,&self.taxonomies),
global_fns::GetTaxonomyUrl::new(&self.config.default_language, &self.taxonomies),
);
}
@ -540,7 +549,11 @@ impl Site {
);
self.tera.register_function(
"get_taxonomy",
global_fns::GetTaxonomy::new(&self.config.default_language, self.taxonomies.clone(), self.library.clone()),
global_fns::GetTaxonomy::new(
&self.config.default_language,
self.taxonomies.clone(),
self.library.clone(),
),
);
}

View File

@ -189,9 +189,10 @@ fn can_build_site_without_live_reload() {
}
#[test]
fn can_build_site_with_live_reload() {
fn can_build_site_with_live_reload_and_drafts() {
let (_, _tmp_dir, public) = build_site_with_setup("test_site", |mut site| {
site.enable_live_reload(1000);
site.include_drafts();
(site, true)
});
@ -230,7 +231,9 @@ fn can_build_site_with_live_reload() {
r#"<a name="continue-reading"></a>"#
));
assert_eq!(file_exists!(public, "posts/draft/index.html"), false);
// Drafts are included
assert!(file_exists!(public, "posts/draft/index.html"));
assert!(file_contains!(public, "sitemap.xml", "draft"));
}
#[test]

View File

@ -94,8 +94,8 @@ impl ResizeImage {
}
}
static DEFAULT_OP: &'static str = "fill";
static DEFAULT_FMT: &'static str = "auto";
static DEFAULT_OP: &str = "fill";
static DEFAULT_FMT: &str = "auto";
const DEFAULT_Q: u8 = 75;
impl TeraFn for ResizeImage {
@ -203,8 +203,9 @@ impl TeraFn for GetTaxonomyUrl {
args.get("name"),
"`get_taxonomy_url` requires a `name` argument with a string value"
);
let lang = optional_arg!(String, args.get("lang"), "`get_taxonomy`: `lang` must be a string")
.unwrap_or_else(|| self.default_lang.clone());
let lang =
optional_arg!(String, args.get("lang"), "`get_taxonomy`: `lang` must be a string")
.unwrap_or_else(|| self.default_lang.clone());
let container = match self.taxonomies.get(&format!("{}-{}", kind, lang)) {
Some(c) => c,
@ -296,7 +297,11 @@ pub struct GetTaxonomy {
default_lang: String,
}
impl GetTaxonomy {
pub fn new(default_lang: &str, all_taxonomies: Vec<Taxonomy>, library: Arc<RwLock<Library>>) -> Self {
pub fn new(
default_lang: &str,
all_taxonomies: Vec<Taxonomy>,
library: Arc<RwLock<Library>>,
) -> Self {
let mut taxonomies = HashMap::new();
for taxo in all_taxonomies {
taxonomies.insert(format!("{}-{}", taxo.kind.name, taxo.kind.lang), taxo);
@ -312,8 +317,9 @@ impl TeraFn for GetTaxonomy {
"`get_taxonomy` requires a `kind` argument with a string value"
);
let lang = optional_arg!(String, args.get("lang"), "`get_taxonomy`: `lang` must be a string")
.unwrap_or_else(|| self.default_lang.clone());
let lang =
optional_arg!(String, args.get("lang"), "`get_taxonomy`: `lang` must be a string")
.unwrap_or_else(|| self.default_lang.clone());
match self.taxonomies.get(&format!("{}-{}", kind, lang)) {
Some(t) => Ok(to_value(t.to_serialized(&self.library.read().unwrap())).unwrap()),
@ -408,8 +414,8 @@ mod tests {
let tags_fr = Taxonomy { kind: taxo_config_fr, items: vec![tag_fr] };
let taxonomies = vec![tags.clone(), tags_fr.clone()];
let static_fn = GetTaxonomy::new(&config.default_language, taxonomies.clone(), library.clone())
;
let static_fn =
GetTaxonomy::new(&config.default_language, taxonomies.clone(), library.clone());
// can find it correctly
let mut args = HashMap::new();
args.insert("kind".to_string(), to_value("tags").unwrap());

View File

@ -55,7 +55,7 @@ date =
# will not be rendered.
weight = 0
# A draft page is only rendered in `zola serve`, they are ignored in `zola build` and `zola check`
# A draft page is only loaded if the `--drafts` flag is passed to `zola build`, `zola serve` or `zola check`
draft = false
# If filled, it will use that slug instead of the filename to make up the URL

View File

@ -56,6 +56,8 @@ You can also point to another config file than `config.toml` like so - the posit
$ zola --config config.staging.toml build
```
By defaults, drafts are not loaded. If you wish to include them, pass the `--drafts` flag.
## serve
This will build and serve the site using a local server. You can also specify
@ -95,12 +97,16 @@ You can also point to another config file than `config.toml` like so - the posit
$ zola --config config.staging.toml serve
```
By defaults, drafts are not loaded. If you wish to include them, pass the `--drafts` flag.
### check
The check subcommand will try to build all pages just like the build command would, but without writing any of the
results to disk. Additionally, it will also check all external links present in Markdown files by trying to fetch
them (links present in the template files will not be checked).
By defaults, drafts are not loaded. If you wish to include them, pass the `--drafts` flag.
## Colored output
Any of the three commands will emit colored output if your terminal supports it.

View File

@ -36,6 +36,10 @@ pub fn build_cli() -> App<'static, 'static> {
.default_value("public")
.takes_value(true)
.help("Outputs the generated site in the given path"),
Arg::with_name("drafts")
.long("drafts")
.takes_value(false)
.help("Include drafts when loading the site"),
]),
SubCommand::with_name("serve")
.about("Serve the site. Rebuild and reload on change automatically")
@ -66,6 +70,10 @@ pub fn build_cli() -> App<'static, 'static> {
.long("watch-only")
.takes_value(false)
.help("Do not start a server, just re-build project on changes"),
Arg::with_name("drafts")
.long("drafts")
.takes_value(false)
.help("Include drafts when loading the site"),
Arg::with_name("open")
.short("O")
.long("open")
@ -74,5 +82,11 @@ pub fn build_cli() -> App<'static, 'static> {
]),
SubCommand::with_name("check")
.about("Try building the project without rendering it. Checks links")
.args(&[
Arg::with_name("drafts")
.long("drafts")
.takes_value(false)
.help("Include drafts when loading the site"),
])
])
}

View File

@ -5,12 +5,20 @@ use site::Site;
use console;
pub fn build(config_file: &str, base_url: Option<&str>, output_dir: &str) -> Result<()> {
pub fn build(
config_file: &str,
base_url: Option<&str>,
output_dir: &str,
include_drafts: bool,
) -> Result<()> {
let mut site = Site::new(env::current_dir().unwrap(), config_file)?;
site.set_output_path(output_dir);
if let Some(b) = base_url {
site.set_base_url(b.to_string());
}
if include_drafts {
site.include_drafts();
}
site.load()?;
console::notify_site_size(&site);
console::warn_about_ignored_pages(&site);

View File

@ -6,7 +6,12 @@ use site::Site;
use console;
pub fn check(config_file: &str, base_path: Option<&str>, base_url: Option<&str>) -> Result<()> {
pub fn check(
config_file: &str,
base_path: Option<&str>,
base_url: Option<&str>,
include_drafts: bool,
) -> Result<()> {
let bp = base_path.map(PathBuf::from).unwrap_or_else(|| env::current_dir().unwrap());
let mut site = Site::new(bp, config_file)?;
// Force the checking of external links
@ -14,6 +19,9 @@ pub fn check(config_file: &str, base_path: Option<&str>, base_url: Option<&str>)
if let Some(b) = base_url {
site.set_base_url(b.to_string());
}
if include_drafts {
site.include_drafts();
}
site.load()?;
console::check_site_summary(&site);
console::warn_about_ignored_pages(&site);

View File

@ -59,16 +59,14 @@ pub fn is_directory_quasi_empty(path: &Path) -> Result<bool> {
pub fn create_new_project(name: &str) -> Result<()> {
let path = Path::new(name);
// Better error message than the rust default
if path.exists() {
if !is_directory_quasi_empty(&path)? {
if name == "." {
bail!("The current directory is not an empty folder (hidden files are ignored).");
} else {
bail!(
"`{}` is not an empty folder (hidden files are ignored).",
path.to_string_lossy().to_string()
)
}
if path.exists() && !is_directory_quasi_empty(&path)? {
if name == "." {
bail!("The current directory is not an empty folder (hidden files are ignored).");
} else {
bail!(
"`{}` is not an empty folder (hidden files are ignored).",
path.to_string_lossy().to_string()
)
}
}

View File

@ -118,6 +118,7 @@ fn create_new_site(
output_dir: &str,
base_url: &str,
config_file: &str,
include_drafts: bool,
) -> Result<(Site, String)> {
let mut site = Site::new(env::current_dir().unwrap(), config_file)?;
@ -132,6 +133,9 @@ fn create_new_site(
site.config.enable_serve_mode();
site.set_base_url(base_url);
site.set_output_path(output_dir);
if include_drafts {
site.include_drafts();
}
site.load()?;
site.enable_live_reload(port);
console::notify_site_size(&site);
@ -148,9 +152,11 @@ pub fn serve(
config_file: &str,
watch_only: bool,
open: bool,
include_drafts: bool,
) -> Result<()> {
let start = Instant::now();
let (mut site, address) = create_new_site(interface, port, output_dir, base_url, config_file)?;
let (mut site, address) =
create_new_site(interface, port, output_dir, base_url, config_file, include_drafts)?;
console::report_elapsed_time(start);
// Setup watchers
@ -375,18 +381,21 @@ pub fn serve(
ChangeKind::StaticFiles => copy_static(&site, &path, &partial_path),
ChangeKind::Sass => reload_sass(&site, &path, &partial_path),
ChangeKind::Themes => {
console::info("-> Themes changed. The whole site will be reloaded.");
console::info(
"-> Themes changed. The whole site will be reloaded.",
);
site = create_new_site(
interface,
port,
output_dir,
base_url,
config_file,
include_drafts,
)
.unwrap()
.0;
rebuild_done_handling(&broadcaster, Ok(()), "/x.js");
},
}
ChangeKind::Config => {
console::info("-> Config changed. The whole site will be reloaded. The browser needs to be refreshed to make the changes visible.");
site = create_new_site(
@ -395,6 +404,7 @@ pub fn serve(
output_dir,
base_url,
config_file,
include_drafts,
)
.unwrap()
.0;
@ -432,18 +442,21 @@ pub fn serve(
(ChangeKind::StaticFiles, p) => copy_static(&site, &path, &p),
(ChangeKind::Sass, p) => reload_sass(&site, &path, &p),
(ChangeKind::Themes, _) => {
console::info("-> Themes changed. The whole site will be reloaded.");
console::info(
"-> Themes changed. The whole site will be reloaded.",
);
site = create_new_site(
interface,
port,
output_dir,
base_url,
config_file,
include_drafts,
)
.unwrap()
.0;
rebuild_done_handling(&broadcaster, Ok(()), "/x.js");
},
}
(ChangeKind::Config, _) => {
console::info("-> Config changed. The whole site will be reloaded. The browser needs to be refreshed to make the changes visible.");
site = create_new_site(
@ -452,6 +465,7 @@ pub fn serve(
output_dir,
base_url,
config_file,
include_drafts,
)
.unwrap()
.0;

View File

@ -48,7 +48,12 @@ fn main() {
console::info("Building site...");
let start = Instant::now();
let output_dir = matches.value_of("output_dir").unwrap();
match cmd::build(config_file, matches.value_of("base_url"), output_dir) {
match cmd::build(
config_file,
matches.value_of("base_url"),
output_dir,
matches.is_present("drafts"),
) {
Ok(()) => console::report_elapsed_time(start),
Err(e) => {
console::unravel_errors("Failed to build the site", &e);
@ -67,6 +72,7 @@ fn main() {
};
let watch_only = matches.is_present("watch_only");
let open = matches.is_present("open");
let include_drafts = matches.is_present("drafts");
// Default one
if port != 1111 && !watch_only && !port_is_available(port) {
@ -85,7 +91,16 @@ fn main() {
let output_dir = matches.value_of("output_dir").unwrap();
let base_url = matches.value_of("base_url").unwrap();
console::info("Building site...");
match cmd::serve(interface, port, output_dir, base_url, config_file, watch_only, open) {
match cmd::serve(
interface,
port,
output_dir,
base_url,
config_file,
watch_only,
open,
include_drafts,
) {
Ok(()) => (),
Err(e) => {
console::unravel_errors("", &e);
@ -100,6 +115,7 @@ fn main() {
config_file,
matches.value_of("base_path"),
matches.value_of("base_url"),
matches.is_present("drafts"),
) {
Ok(()) => console::report_elapsed_time(start),
Err(e) => {