sita 0.2.0

Sita: static site generator (SSG) for Markdown and HTML
# Errors using thiserror

For errors we use the crate `thiserror` because it is well-maintained, pragmatic, and provides detailed errors suitable for libraries. We removed the crate `error-chain` because it wasn't well-maintained.


## pub enum Error

The pattern for error definition looks like this:

```rust
#[derive(thiserror::Error, Debug)]
pub enum Error {

    #[error("AlfaBravo ➡ {0:?}")]
    AlfaBravo(std::io::Error),

    #[error("CharlieDelta ➡ echo: {echo:?}, foxtrot: {foxtrot:?}")]
    CharlieDelta {
        echo: String,
        foxtrot: String,
    }

}
```

### Our convention

Our convention for `pub enum Error`:

* The enum is named `Error`, not anything else. A side effect of this convention: in each file, the file's enum `Error` convention supersedes any other `Error` such as `std::error::Error`, i.e. in each file, any other `Error` must be fully qualified.

* The error message starts with the enum variant and a Unicode right arrow.

* The error message for a struct includes each field and its debug representation, so long as it's practical, i.e. we want to behave akin to a library error, and we want print as much information as possible for developers who are debugging.


## Catch errors

Our preferred pattern for handling a `Result` uses `map_or_else` to return the error `err` or unwrap the value `val` like this:

```rust
foo().map_or_else(
    |err| MyError::StdIoError(err),
    |val| val.ok()
)?;
```


### Catch errors in main

Our convention is a file `main.rs` where the setup happens:

```rust
fn main() {
    env_logger::init();
    match crate::app::run::run() {
        Ok(()) => {
            std::process::exit(0);
        }
        Err(err) => {
            error!("{:?}", err);
            std::process::exit(1);
        }
    }
}
```

Our convention is a file `run.rs` where the work happens:

```rust
pub(crate) fn run() -> Result<()> {
    Ok(())
}
```