Browse Source

Merge pull request #644 from getzola/next

v0.7.0
index-subcmd
Vincent Prouillet GitHub 5 years ago
parent
commit
986437546c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 590 additions and 550 deletions
  1. +9
    -0
      CHANGELOG.md
  2. +473
    -443
      Cargo.lock
  3. +1
    -1
      Cargo.toml
  4. +30
    -31
      README.md
  5. +19
    -0
      components/rendering/src/shortcode.rs
  6. +10
    -6
      components/site/src/lib.rs
  7. +13
    -0
      components/site/src/sitemap.rs
  8. +1
    -1
      components/templates/src/builtins/sitemap.xml
  9. +1
    -1
      components/templates/src/builtins/split_sitemap_index.xml
  10. +1
    -0
      components/templates/src/global_fns/load_data.rs
  11. +2
    -1
      components/utils/test-files/test.toml
  12. +0
    -9
      docs/content/documentation/getting-started/cli-usage.md
  13. +3
    -0
      is-ehh.svg
  14. +3
    -0
      is-no.svg
  15. +3
    -0
      is-yes.svg
  16. +0
    -10
      src/cli.rs
  17. +2
    -9
      src/cmd/build.rs
  18. +17
    -22
      src/cmd/serve.rs
  19. +2
    -16
      src/main.rs

+ 9
- 0
CHANGELOG.md View File

@@ -1,5 +1,14 @@
# Changelog # Changelog


## 0.7.0 (2019-04-28)

### Breaking
- Remove --base-path option, it broke `serve` on Windows and wasn't properly tested

### Other
- Strip wrapping whitespaces from shortcodes
- Sort sitemap elements by permalink`

## 0.6.0 (2019-03-25) ## 0.6.0 (2019-03-25)


### Breaking ### Breaking


+ 473
- 443
Cargo.lock
File diff suppressed because it is too large
View File


+ 1
- 1
Cargo.toml View File

@@ -1,6 +1,6 @@
[package] [package]
name = "zola" name = "zola"
version = "0.6.0"
version = "0.7.0"
authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"] authors = ["Vincent Prouillet <prouillet.vincent@gmail.com>"]
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"


+ 30
- 31
README.md View File

@@ -1,4 +1,5 @@
# zola (né Gutenberg) # zola (né Gutenberg)

[![Build Status](https://travis-ci.com/getzola/zola.svg?branch=master)](https://travis-ci.com/getzola/zola) [![Build Status](https://travis-ci.com/getzola/zola.svg?branch=master)](https://travis-ci.com/getzola/zola)
[![Build status](https://ci.appveyor.com/api/projects/status/i0ufvx2sdm2cmawo/branch/master?svg=true)](https://ci.appveyor.com/project/Keats/zola/branch/master) [![Build status](https://ci.appveyor.com/api/projects/status/i0ufvx2sdm2cmawo/branch/master?svg=true)](https://ci.appveyor.com/project/Keats/zola/branch/master)


@@ -9,32 +10,31 @@ in the `docs/content` folder of the repository and the community can use [its fo


## Comparisons with other static site generators ## Comparisons with other static site generators


| | Zola | Cobalt | Hugo | Pelican |
|:-------------------------------:|:---------:|--------|------|---------|
| Single binary | ✔ | ✔ | ✔ | ✕ |
| Language | Rust | Rust | Go | Python |
| Syntax highlighting | ✔ | ✔ | ✔ | ✔ |
| Sass compilation | ✔ | ✔ | ✔ | ✔ |
| Assets co-location | ✔ | ✔ | ✔ | ✔ |
| Multilingual site | ✔ | ✕ | ✔ | ✔ |
| Image processing | ✔ | ✕ | ✔ | ✔ |
| Sane & powerful template engine | ✔ | ~ | ~ | ✔ |
| Themes | ✔ | ✕ | ✔ | ✔ |
| Shortcodes | ✔ | ✕ | ✔ | ✔ |
| Internal links | ✔ | ✕ | ✔ | ✔ |
| Link checker | ✔ | ✕ | ✕ | ✔ |
| Table of contents | ✔ | ✕ | ✔ | ✔ |
| Automatic header anchors | ✔ | ✕ | ✔ | ✔ |
| Aliases | ✔ | ✕ | ✔ | ✔ |
| Pagination | ✔ | ✕ | ✔ | ✔ |
| Custom taxonomies | ✔ | ✕ | ✔ | ✕ |
| Search | ✔ | ✕ | ✕ | ✔ |
| Data files | ✔ | ✔ | ✔ | ✕ |
| LiveReload | ✔ | ✕ | ✔ | ✔ |
| Netlify support | ~ | ✕ | ✔ | ✕ |
| Breadcrumbs | ✔ | ✕ | ✕ | ✔ |
| Custom output formats | ✕ | ✕ | ✔ | ? |

| | Zola | Cobalt | Hugo | Pelican |
|:--------------------------------|:--------------------:|:--------------------:|:--------------------:|:--------------------:|
| Single binary | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![no](./is-no.svg) |
| Language | Rust | Rust | Go | Python |
| Syntax highlighting | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Sass compilation | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Assets co-location | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Multilingual site | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Image processing | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Sane & powerful template engine | ![yes](./is-yes.svg) | ![ehh](./is-ehh.svg) | ![ehh](./is-ehh.svg) | ![yes](./is-yes.svg) |
| Themes | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Shortcodes | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Internal links | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Link checker | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) |
| Table of contents | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Automatic header anchors | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Aliases | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Pagination | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Custom taxonomies | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![no](./is-no.svg) |
| Search | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) |
| Data files | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) | ![no](./is-no.svg) |
| LiveReload | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![yes](./is-yes.svg) |
| Netlify support | ![ehh](./is-ehh.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![no](./is-no.svg) |
| Breadcrumbs | ![yes](./is-yes.svg) | ![no](./is-no.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) |
| Custom output formats | ![no](./is-no.svg) | ![no](./is-no.svg) | ![yes](./is-yes.svg) | ![no](./is-no.svg) |


### Supported content formats ### Supported content formats


@@ -45,11 +45,10 @@ in the `docs/content` folder of the repository and the community can use [its fo


### Template engine explanation ### Template engine explanation


Cobalt gets `~` as, while based on [Liquid](https://shopify.github.io/liquid/), the Rust library doesn't implement all its features but there is no documentation on what is and isn't implemented. The errors are also cryptic. Liquid itself is not powerful enough to do some of things you can do in Jinja2, Go templates or Tera.
Cobalt gets ![ehh](./is-ehh.svg) because, while based on [Liquid](https://shopify.github.io/liquid/), the Rust library doesn't implement all its features and there is no documentation on what is and isn't implemented; the errors are cryptic; and Liquid itself is not powerful enough to do some of things you can do in Jinja2, Go templates, or Tera.


Hugo gets `~`. It is probably the most powerful template engine in the list after Jinja2 (hard to beat python code in templates) but personally drives me insane, to the point of writing my own template engine and static site generator. Yes, this is a bit biased.
Hugo gets ![ehh](./is-ehh.svg) because while it is probably the most powerful template engine in the list, after Jinja2, it personally drives me insane, to the point of writing my own template engine and static site generator. Yes, this is a bit biased.


### Pelican notes ### Pelican notes
Many features of Pelican are coming from plugins, which might be tricky
to use because of version mismatch or lacking documentation. Netlify supports Python
and Pipenv but you still need to install your dependencies manually.

Many features of Pelican are coming from plugins, which might be tricky to use because of version mismatch or lacking documentation. Netlify supports Python and Pipenv but you still need to install your dependencies manually.

+ 19
- 0
components/rendering/src/shortcode.rs View File

@@ -16,6 +16,7 @@ pub struct ContentParser;


lazy_static! { lazy_static! {
static ref MULTIPLE_NEWLINE_RE: Regex = Regex::new(r"\n\s*\n").unwrap(); static ref MULTIPLE_NEWLINE_RE: Regex = Regex::new(r"\n\s*\n").unwrap();
static ref OUTER_NEWLINE_RE: Regex = Regex::new(r"^\s*\n|\n\s*$").unwrap();
} }


fn replace_string_markers(input: &str) -> String { fn replace_string_markers(input: &str) -> String {
@@ -122,6 +123,8 @@ fn render_shortcode(
// at indentation, making the output a code block. // at indentation, making the output a code block.
let res = MULTIPLE_NEWLINE_RE.replace_all(&res, "\n"); let res = MULTIPLE_NEWLINE_RE.replace_all(&res, "\n");


let res = OUTER_NEWLINE_RE.replace_all(&res, "");

Ok(res.to_string()) Ok(res.to_string())
} }


@@ -411,4 +414,20 @@ Some body {{ hello() }}{%/* end */%}"#,
let res = render_shortcodes("Body\n {% youtube() %}\nHello \n World{% end %}", &tera); let res = render_shortcodes("Body\n {% youtube() %}\nHello \n World{% end %}", &tera);
assert_eq!(res, "Body\n Hello \n World"); assert_eq!(res, "Body\n Hello \n World");
} }

#[test]
fn outer_newlines_removed_from_shortcodes_with_body() {
let mut tera = Tera::default();
tera.add_raw_template("shortcodes/youtube.html", " \n {{body}} \n ").unwrap();
let res = render_shortcodes("\n{% youtube() %} \n content \n {% end %}\n", &tera);
assert_eq!(res, "\n content \n");
}

#[test]
fn outer_newlines_removed_from_inline_shortcodes() {
let mut tera = Tera::default();
tera.add_raw_template("shortcodes/youtube.html", " \n Hello, Zola. \n ").unwrap();
let res = render_shortcodes("\n{{ youtube() }}\n", &tera);
assert_eq!(res, "\n Hello, Zola. \n");
}
} }

+ 10
- 6
components/site/src/lib.rs View File

@@ -66,7 +66,7 @@ pub struct Site {


impl Site { impl Site {
/// Parse a site at the given path. Defaults to the current dir /// Parse a site at the given path. Defaults to the current dir
/// Passing in a path is possible using the `base-path` command line build option
/// Passing in a path is only used in tests
pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> { pub fn new<P: AsRef<Path>>(path: P, config_file: &str) -> Result<Site> {
let path = path.as_ref(); let path = path.as_ref();
let mut config = get_config(path, config_file); let mut config = get_config(path, config_file);
@@ -777,11 +777,15 @@ impl Site {
ensure_directory_exists(&self.output_path)?; ensure_directory_exists(&self.output_path)?;


let library = self.library.read().unwrap(); let library = self.library.read().unwrap();
let all_sitemap_entries = sitemap::find_entries(
&library,
&self.taxonomies[..],
&self.config,
);
let all_sitemap_entries = {
let mut all_sitemap_entries = sitemap::find_entries(
&library,
&self.taxonomies[..],
&self.config,
);
all_sitemap_entries.sort();
all_sitemap_entries
};
let sitemap_limit = 30000; let sitemap_limit = 30000;


if all_sitemap_entries.len() < sitemap_limit { if all_sitemap_entries.len() < sitemap_limit {


+ 13
- 0
components/site/src/sitemap.rs View File

@@ -5,6 +5,7 @@ use std::collections::{HashSet};
use tera::{Map, Value}; use tera::{Map, Value};
use config::{Config}; use config::{Config};
use library::{Library, Taxonomy}; use library::{Library, Taxonomy};
use std::cmp::Ordering;


/// The sitemap only needs links, potentially date and extra for pages in case of updates /// The sitemap only needs links, potentially date and extra for pages in case of updates
/// for examples so we trim down all entries to only that /// for examples so we trim down all entries to only that
@@ -39,6 +40,18 @@ impl<'a> SitemapEntry<'a> {
} }
} }


impl<'a> PartialOrd for SitemapEntry<'a> {
fn partial_cmp(&self, other: &SitemapEntry) -> Option<Ordering> {
Some(self.permalink.as_ref().cmp(other.permalink.as_ref()))
}
}

impl<'a> Ord for SitemapEntry<'a> {
fn cmp(&self, other: &SitemapEntry) -> Ordering {
self.permalink.as_ref().cmp(other.permalink.as_ref())
}
}

/// Finds out all the links to put in a sitemap from the pages/sections/taxonomies /// Finds out all the links to put in a sitemap from the pages/sections/taxonomies
/// There are no duplicate permalinks in the output vec /// There are no duplicate permalinks in the output vec
pub fn find_entries<'a>(library: &'a Library, taxonomies: &'a [Taxonomy], config: &'a Config) -> Vec<SitemapEntry<'a>> { pub fn find_entries<'a>(library: &'a Library, taxonomies: &'a [Taxonomy], config: &'a Config) -> Vec<SitemapEntry<'a>> {


+ 1
- 1
components/templates/src/builtins/sitemap.xml View File

@@ -1,4 +1,4 @@
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
{% for sitemap_entry in entries %} {% for sitemap_entry in entries %}
<url> <url>
<loc>{{ sitemap_entry.permalink | safe }}</loc> <loc>{{ sitemap_entry.permalink | safe }}</loc>


+ 1
- 1
components/templates/src/builtins/split_sitemap_index.xml View File

@@ -1,4 +1,4 @@
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemapindex xmlns="https://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd">
{% for sitemap in sitemaps %} {% for sitemap in sitemaps %}
<sitemap> <sitemap>
<loc>{{ sitemap }}</loc> <loc>{{ sitemap }}</loc>


+ 1
- 0
components/templates/src/global_fns/load_data.rs View File

@@ -431,6 +431,7 @@ mod tests {
json!({ json!({
"category": { "category": {
"date": "1979-05-27T07:32:00Z", "date": "1979-05-27T07:32:00Z",
"lt1": "07:32:00",
"key": "value" "key": "value"
}, },
}) })


+ 2
- 1
components/utils/test-files/test.toml View File

@@ -1,3 +1,4 @@
[category] [category]
key = "value" key = "value"
date = 1979-05-27T07:32:00Z
date = 1979-05-27T07:32:00Z
lt1 = 07:32:00

+ 0
- 9
docs/content/documentation/getting-started/cli-usage.md View File

@@ -36,14 +36,6 @@ $ zola build --base-url $DEPLOY_URL
This is useful for example when you want to deploy previews of a site to a dynamic URL, such as Netlify This is useful for example when you want to deploy previews of a site to a dynamic URL, such as Netlify
deploy previews. deploy previews.


You can override the default `base_path` by passing a new directory to the `base-path` flag. If no `base-path` flag
is provided, zola defaults to your current working directory. This is useful if your zola project is located in
a different directory from where you're executing zola from.

```bash
$ zola build --base-path /path/to/zola/site
```

You can override the default output directory 'public' by passing a other value to the `output-dir` flag. You can override the default output directory 'public' by passing a other value to the `output-dir` flag.


```bash ```bash
@@ -75,7 +67,6 @@ $ zola serve --interface 0.0.0.0
$ zola serve --interface 0.0.0.0 --port 2000 $ zola serve --interface 0.0.0.0 --port 2000
$ zola serve --interface 0.0.0.0 --base-url 127.0.0.1 $ zola serve --interface 0.0.0.0 --base-url 127.0.0.1
$ zola serve --interface 0.0.0.0 --port 2000 --output-dir www/public $ zola serve --interface 0.0.0.0 --port 2000 --output-dir www/public
$ zola serve --interface 0.0.0.0 --port 2000 --base-path mysite/ --output-dir mysite/www/public
$ zola serve --watch-only $ zola serve --watch-only
``` ```




+ 3
- 0
is-ehh.svg View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" style="fill:#dbab09" width="16" height="16" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="8"/>
</svg>

+ 3
- 0
is-no.svg View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" style="fill:#cb2431" width="16" height="16" viewBox="0 0 24 24">
<path d="M23 20.168l-8.185-8.187 8.185-8.174-2.832-2.807-8.182 8.179-8.176-8.179-2.81 2.81 8.186 8.196-8.186 8.184 2.81 2.81 8.203-8.192 8.18 8.192z"/>
</svg>

+ 3
- 0
is-yes.svg View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" style="fill:#28a745" width="16" height="16" viewBox="0 0 24 24">
<path d="M9 21.035l-9-8.638 2.791-2.87 6.156 5.874 12.21-12.436 2.843 2.817z"/>
</svg>

+ 0
- 10
src/cli.rs View File

@@ -30,11 +30,6 @@ pub fn build_cli() -> App<'static, 'static> {
.long("base-url") .long("base-url")
.takes_value(true) .takes_value(true)
.help("Force the base URL to be that value (default to the one in config.toml)"), .help("Force the base URL to be that value (default to the one in config.toml)"),
Arg::with_name("base_path")
.short("b")
.long("base-path")
.takes_value(true)
.help("Force the base site path to a certain directory [default: the current working directory]"),
Arg::with_name("output_dir") Arg::with_name("output_dir")
.short("o") .short("o")
.long("output-dir") .long("output-dir")
@@ -61,11 +56,6 @@ pub fn build_cli() -> App<'static, 'static> {
.default_value("public") .default_value("public")
.takes_value(true) .takes_value(true)
.help("Outputs the generated site in the given path"), .help("Outputs the generated site in the given path"),
Arg::with_name("base_path")
.short("b")
.long("base-path")
.takes_value(true)
.help("Force the base site path to a certain directory [default: the current working directory]"),
Arg::with_name("base_url") Arg::with_name("base_url")
.short("u") .short("u")
.long("base-url") .long("base-url")


+ 2
- 9
src/cmd/build.rs View File

@@ -1,19 +1,12 @@
use std::env; use std::env;
use std::path::PathBuf;


use errors::Result; use errors::Result;
use site::Site; use site::Site;


use console; use console;


pub fn build(
config_file: &str,
base_path: Option<&str>,
base_url: Option<&str>,
output_dir: &str,
) -> Result<()> {
let bp = base_path.map(PathBuf::from).unwrap_or(env::current_dir().unwrap());
let mut site = Site::new(bp, config_file)?;
pub fn build(config_file: &str, base_url: Option<&str>, output_dir: &str) -> Result<()> {
let mut site = Site::new(env::current_dir().unwrap(), config_file)?;
site.set_output_path(output_dir); site.set_output_path(output_dir);
if let Some(b) = base_url { if let Some(b) = base_url {
site.set_base_url(b.to_string()); site.set_base_url(b.to_string());


+ 17
- 22
src/cmd/serve.rs View File

@@ -86,8 +86,8 @@ impl<S> Middleware<S> for NotFoundHandler {
} }
} }


fn livereload_handler(_: &HttpRequest) -> &'static str {
LIVE_RELOAD
fn livereload_handler(_: &HttpRequest) -> HttpResponse {
HttpResponse::Ok().content_type("text/javascript").body(LIVE_RELOAD)
} }


fn rebuild_done_handling(broadcaster: &Option<Sender>, res: Result<()>, reload_path: &str) { fn rebuild_done_handling(broadcaster: &Option<Sender>, res: Result<()>, reload_path: &str) {
@@ -114,15 +114,14 @@ fn rebuild_done_handling(broadcaster: &Option<Sender>, res: Result<()>, reload_p
} }
} }


fn create_new_site<P: AsRef<Path>>(
fn create_new_site(
interface: &str, interface: &str,
port: u16, port: u16,
output_dir: &str, output_dir: &str,
base_path: P,
base_url: &str, base_url: &str,
config_file: &str, config_file: &str,
) -> Result<(Site, String)> { ) -> Result<(Site, String)> {
let mut site = Site::new(base_path, config_file)?;
let mut site = Site::new(env::current_dir().unwrap(), config_file)?;


let base_address = format!("{}:{}", base_url, port); let base_address = format!("{}:{}", base_url, port);
let address = format!("{}:{}", interface, port); let address = format!("{}:{}", interface, port);
@@ -167,15 +166,12 @@ pub fn serve(
interface: &str, interface: &str,
port: u16, port: u16,
output_dir: &str, output_dir: &str,
base_path: Option<&str>,
base_url: &str, base_url: &str,
config_file: &str, config_file: &str,
watch_only: bool, watch_only: bool,
) -> Result<()> { ) -> Result<()> {
let start = Instant::now(); let start = Instant::now();
let bp = base_path.map(PathBuf::from).unwrap_or(env::current_dir().unwrap());
let (mut site, address) =
create_new_site(interface, port, output_dir, bp.clone(), base_url, config_file)?;
let (mut site, address) = create_new_site(interface, port, output_dir, base_url, config_file)?;
console::report_elapsed_time(start); console::report_elapsed_time(start);


// Setup watchers // Setup watchers
@@ -184,28 +180,28 @@ pub fn serve(
let (tx, rx) = channel(); let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap(); let mut watcher = watcher(tx, Duration::from_secs(1)).unwrap();
watcher watcher
.watch(bp.join("content/"), RecursiveMode::Recursive)
.watch("content/", RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?; .map_err(|e| ZolaError::chain("Can't watch the `content` folder. Does it exist?", e))?;
watcher watcher
.watch(bp.join(config_file), RecursiveMode::Recursive)
.watch(config_file, RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?; .map_err(|e| ZolaError::chain("Can't watch the `config` file. Does it exist?", e))?;


if bp.join("static").exists() {
if Path::new("static").exists() {
watching_static = true; watching_static = true;
watcher watcher
.watch(bp.join("static/"), RecursiveMode::Recursive)
.watch("static/", RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?; .map_err(|e| ZolaError::chain("Can't watch the `static` folder.", e))?;
} }


if bp.join("templates").exists() {
if Path::new("templates").exists() {
watching_templates = true; watching_templates = true;
watcher watcher
.watch(bp.join("templates/"), RecursiveMode::Recursive)
.watch("templates/", RecursiveMode::Recursive)
.map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?; .map_err(|e| ZolaError::chain("Can't watch the `templates` folder.", e))?;
} }


// Sass support is optional so don't make it an error to no have a sass folder // Sass support is optional so don't make it an error to no have a sass folder
let _ = watcher.watch(bp.join("sass/"), RecursiveMode::Recursive);
let _ = watcher.watch("sass/", RecursiveMode::Recursive);


let ws_address = format!("{}:{}", interface, site.live_reload.unwrap()); let ws_address = format!("{}:{}", interface, site.live_reload.unwrap());
let output_path = Path::new(output_dir).to_path_buf(); let output_path = Path::new(output_dir).to_path_buf();
@@ -262,6 +258,8 @@ pub fn serve(
None None
}; };


let pwd = env::current_dir().unwrap();

let mut watchers = vec!["content", "config.toml"]; let mut watchers = vec!["content", "config.toml"];
if watching_static { if watching_static {
watchers.push("static"); watchers.push("static");
@@ -275,7 +273,7 @@ pub fn serve(


println!( println!(
"Listening for changes in {}{}{{{}}}", "Listening for changes in {}{}{{{}}}",
bp.display(),
pwd.display(),
MAIN_SEPARATOR, MAIN_SEPARATOR,
watchers.join(", ") watchers.join(", ")
); );
@@ -351,8 +349,7 @@ pub fn serve(
if path.is_file() && is_temp_file(&path) { if path.is_file() && is_temp_file(&path) {
continue; continue;
} }
let (change_kind, partial_path) =
detect_change_kind(&bp.canonicalize().unwrap(), &path);
let (change_kind, partial_path) = detect_change_kind(&pwd, &path);


// We only care about changes in non-empty folders // We only care about changes in non-empty folders
if path.is_dir() && is_folder_empty(&path) { if path.is_dir() && is_folder_empty(&path) {
@@ -384,7 +381,6 @@ pub fn serve(
interface, interface,
port, port,
output_dir, output_dir,
bp.clone(),
base_url, base_url,
config_file, config_file,
) )
@@ -405,7 +401,7 @@ pub fn serve(
); );


let start = Instant::now(); let start = Instant::now();
match detect_change_kind(&bp.canonicalize().unwrap(), &path) {
match detect_change_kind(&pwd, &path) {
(ChangeKind::Content, _) => { (ChangeKind::Content, _) => {
console::info(&format!("-> Content changed {}", path.display())); console::info(&format!("-> Content changed {}", path.display()));
// Force refresh // Force refresh
@@ -424,7 +420,6 @@ pub fn serve(
interface, interface,
port, port,
output_dir, output_dir,
bp.clone(),
base_url, base_url,
config_file, config_file,
) )


+ 2
- 16
src/main.rs View File

@@ -46,12 +46,7 @@ fn main() {
console::info("Building site..."); console::info("Building site...");
let start = Instant::now(); let start = Instant::now();
let output_dir = matches.value_of("output_dir").unwrap(); let output_dir = matches.value_of("output_dir").unwrap();
match cmd::build(
config_file,
matches.value_of("base_path"),
matches.value_of("base_url"),
output_dir,
) {
match cmd::build(config_file, matches.value_of("base_url"), output_dir) {
Ok(()) => console::report_elapsed_time(start), Ok(()) => console::report_elapsed_time(start),
Err(e) => { Err(e) => {
console::unravel_errors("Failed to build the site", &e); console::unravel_errors("Failed to build the site", &e);
@@ -84,18 +79,9 @@ fn main() {
} }
let watch_only = matches.is_present("watch_only"); let watch_only = matches.is_present("watch_only");
let output_dir = matches.value_of("output_dir").unwrap(); let output_dir = matches.value_of("output_dir").unwrap();
let base_path = matches.value_of("base_path");
let base_url = matches.value_of("base_url").unwrap(); let base_url = matches.value_of("base_url").unwrap();
console::info("Building site..."); console::info("Building site...");
match cmd::serve(
interface,
port,
output_dir,
base_path,
base_url,
config_file,
watch_only,
) {
match cmd::serve(interface, port, output_dir, base_url, config_file, watch_only) {
Ok(()) => (), Ok(()) => (),
Err(e) => { Err(e) => {
console::unravel_errors("", &e); console::unravel_errors("", &e);


Loading…
Cancel
Save