# ![Zas](https://i.imgur.com/e9abWRX.png) Most simple static site generator ever. ## Why another one? C'mon, you must be kidding I just wanted to set up a simple website, just some pages, using Jekyll, and it didn't feel right. I didn't want a blog. I checked other projects, but they were incomplete, cumbersome, or solved the wrong problem (blogs, blogs everywhere). I wanted a zen-like experience: a layout and some Markdown files as pages with unobtrusive structure and configuration. Yes, it is another NIH, but... I think Zas is a different kind of beast. I admit that I probably overlooked some projects at the moment. ### What is the difference? 1. Gophers. Yes, there is [Hugo](http://gohugo.io/) (kudos!) but... Who wants to learn another directory layout? There is also [Hastie](https://github.com/mkaz/hastie) and [lots of other static site generators](https://jamstack.org/generators/). 2. Pure Markdown. And HTML, if you want. 3. Just a loop. Zas loops over the current directory (and subdirectories), converting .md and .html files and copying everything else as-is - except dot-files and dot-directories, which are ignored entirely. 4. Your imagination is your limit. Zas has a simple extension mechanism based on subcommands. Do you need to handle a blog with Zas? Install/create a new extension and do it! 5. Unobtrusive structure, no `_` files. More in the [Usage section](#usage). ## Usage Install: ```sh go install github.com/darccio/zas/cmd/zas@latest ``` Go to your site's directory and do: ```sh zas init ``` Zas will create a `.zas` directory with sane defaults, including a starter `.zas/layout.html` - replace it with your own whenever you like. ```sh zas ``` Yes. Enough. Your delightful site is on .zas/deploy. Enjoy. What is happening here? Well, Zas calls the `generate` subcommand by default. This subcommand accepts the following flags: * `-verbose`: print ALL the things! * `-full`: generate all the input files. By default, it has an incremental mode that keeps source and deploys directories in sync - it also picks up changes to `layout.html`, `config.yml`, `i18n.yml`, and any `.zas.yml` in a page's own directory tree, not just the page's own source, and it follows a page's (or `layout.html`'s own) `` targets too, recursively through further `Markdown`/`Html` embeds. Two narrower gaps remain: an `` whose `src` is itself a template action can't be resolved without running the page's own template, and an `mzs*` MIME type plugin's `src` file is tracked but whatever else the plugin reads isn't - use `-full` after editing either of those. ## Configuration and extension Zas is like water. It can flow, or it can cr... Nah, Zas doesn't crash (please file an issue if it does). Everything is configurable at .zas/config.yml. It is initialized with default values the first time you run `zas init`; running it again leaves an existing config.yml (and layout.html) alone unless you pass `-force`, which overwrites both with their defaults. You can override the `site` config section in two ways: 1. HTML comment in files (most precedence). 2. `.zas.yml` file at the directory level. Its scope is its directory and subdirectories (until another `.zas.yml` is found). By default, dot-files and dot-directories (anything whose name starts with `.`) are skipped entirely, at any depth - `.git`, editor swap files, and so on. A site that genuinely needs a specific top-level dot-directory published - `.well-known/`, for example, which browsers and ACME clients expect to find at a site's root - can opt it back in with `allowed_dotdirs` under the `zas` section: ```yaml zas: allowed_dotdirs: [".well-known"] ``` Only an exact, top-level match is honored: no prefix or glob matching, and a dot-directory nested anywhere - including inside an allowed one - still gets skipped. `.zas` and `.git` can never be allowlisted this way, no matter what's listed in config. Here's every key Zas itself understands in `config.yml`, together in one place (a real site's own file will typically be much shorter, since every one of these has a default and nothing here is required): ```yaml zas: layout: .zas/layout.html # default: .zas/layout.html deploy: .zas/deploy # default: .zas/deploy allowed_dotdirs: [".well-known"] # default: none - see above site: baseurl: https://example.com # default: http://example.com - see {{.Site.BaseURL}} below language: en # default: en - see {{.Language}} and I18N below image: https://example.com/og-image.png # default: unset - see {{.Site.Image}} below sitemap: true # default: false - see "Sitemap generation" below mimetypes: text/markdown: markdown # default text/plain: plain # default text/html: html # default text/yaml+myplugin: myplugin # example custom MIME type plugin - see below ``` This is illustrative, not exhaustive of every key a *plugin* might read from its own section: plugins are free to define and read their own config (see "Beware" under Plugins below), and `config.yml` will happily carry whatever additional sections they need. To extend Zas functionality, you can use and create plugins. You can develop them in any language (not only in Golang) thanks to Unix magic. And more gophers. ### Plugins Any prefixed by `zs` or `mzs` is a potential Zas plugin. All plugins are Zas subcommands. For example, we invoke an imaginary plugin called `zshello` as a subcommand: ```sh $ zas hello Hello! $ zas hello World Hello World! ``` That's all. Zas passes any command-line argument after subcommand name to `zshello`. (The same `zshello` binary is also reachable from page content - see the script tag mechanism below.) **Beware:** Zas won't pass any configuration information. Plugins are responsible for reading configuration, even from directory and page levels. Helper libraries in different languages are welcome! Also, plugins are free to use `.zas` directory for their own needs. I recommend creating this directory's structure to avoid colliding issues: ```text .zas +-- plugins | +-- github.com | +-- darccio | +-- myplugin +-- ... ``` Any `zs` plugin can also be invoked from page content through a script tag with type `application/zas+myplugin`: ```html ``` The tag is deleted and replaced by whatever the plugin writes to stdout, as HTML. `data-args` supplies argv, split with shell-like quoting - `'single'` and `"double"` quotes group an argument containing spaces, and a backslash escapes the next character - but nothing here is ever handed to an actual shell, so none of `$`, `` ` ``, `*`, `~`, `#`, `|`, `;`, `&`, `<`, `>` are special; they reach the plugin literally. Unlike an ``, this tag's own inner content isn't parsed as HTML at all: `