commit 79dedac6af25eb1ec77a3ae54aed78cd5d058d80 Author: dat-adi Date: Sat Jan 1 10:31:18 2022 +0530 Initial setup diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..fd9e59e --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,32 @@ +name: Documentation + +on: push + +jobs: + build: + name: x86_64-unknown-linux-gnu + runs-on: ubuntu-latest + if: github.ref != 'refs/heads/main' + steps: + - name: 'checkout' + uses: actions/checkout@v2 + + - name: 'build' + uses: shalzz/zola-deploy-action@v0.13.0 + env: + PAGES_BRANCH: gh-pages + BUILD_DIR: . + TOKEN: ${{ secrets.TOKEN }} + build_and_deploy: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + steps: + - name: 'checkout' + uses: actions/checkout@v2 + - name: 'build and deploy' + uses: shalzz/zola-deploy-action@v0.13.0 + env: + PAGES_BRANCH: master + BUILD_DIR: . + TOKEN: ${{ secrets.PUBLIC_TOKEN }} + REPOSITORY: dat-adi/dat-adi.github.io diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..220c168 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Roman Soldatenkov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..caade58 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +## An easy way to create a document library for your project + +Demo: [https://easydocs.codeandmedia.com/](https://easydocs.codeandmedia.com/) + +This theme for [Zola](https://getzola.org) (static site engine) helps you build and publish your project docs easily and fast. Zola is just one binary that outputs html-pages and additional static assets after building your docs written in Markdown. Thus, you can take the theme, your md-files, Zola and gain flexible and simple website for documentation. + +### Step-by-step + +As you may have heard Zola is quite flexible :) So, the scenario below is one of hundreds possible ways to make things done, feel free to find your best. Also, Zola provides their own mechanism to install and use themes, see [the docs](https://www.getzola.org/documentation/themes/installing-and-using-themes/). + +1. Fork the repo and replace demo-content inside content folder with yours. But take a look to _index.md files. It contains `title` and when you want to have anchor right of your headers add `insert_anchor_links = "right"` to each index. `theme.toml`, screenshot and readme may be deleted too. +2. Inside `config.toml` change URL and title on your own. In extra section you can specify path to your GitHub API for version below the logo on nav, favicon and logo itself. Or just remove the lines if you don't need it. Also, you can configure or turn on some additional settings related to Zola. [Specification is here](https://www.getzola.org/documentation/getting-started/configuration/). +3. In sass/_variables.scss you may change font, color or backgound if you want. +4. Almost done. Now, you should decide how you want to build and where will be hosted your website. You can build it locally and upload to somewhere. Or build in GitHub Actions and host on GitHub Pages / Netlify / CloudFlare Pages / AnyS3CloudStorage. [Howto for GitHub Pages](https://www.getzola.org/documentation/deployment/github-pages/). [My example](https://github.com/o365hq/o365hq.com/blob/main/.github/workflows/main.yml) of GitHub workflow with 2-steps build (the first checks for links and spelling errors, the second uploads to Azure). [Dockerfile](https://github.com/codeandmedia/zola_docsascode_theme/blob/master/Dockerfile) to make Docker image. + +Enjoy your docs! + +* _Icons: [Office UI Fabric Icons](https://uifabricicons.azurewebsites.net/)_ +* _Copy-code-button: [Aaron Luna](https://aaronluna.dev/blog/add-copy-button-to-code-blocks-hugo-chroma/)_ \ No newline at end of file diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..a64e473 --- /dev/null +++ b/config.toml @@ -0,0 +1,13 @@ +base_url = "https://easydocs.codeandmedia.com" +title = "Docs" +compile_sass = true +build_search_index = true + +[markdown] +highlight_code = true +highlight_theme = "base16-ocean-light" + +[extra] +logo = "https://easydocs.codeandmedia.com/logo.svg" +release = "https://api.github.com/repos/getzola/zola/releases/latest" +favicon = "https://www.getzola.org/favicon.ico" \ No newline at end of file diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..3e1362a --- /dev/null +++ b/content/_index.md @@ -0,0 +1,22 @@ ++++ +title = "Magic Bridges" +insert_anchor_links = "right" ++++ + +## Forge Federation + +This theme for [Zola](https://getzola.org) (static site engine) helps you build and publish your project docs easily and fast. Zola is just one binary that outputs html-pages and additional static assets after building your docs written in Markdown. Thus, you can take the theme, your md-files, Zola and gain flexible and simple website for documentation. + +### Step-by-step + +As you may have heard Zola is quite flexible :) So, the scenario below is one of hundreds possible ways to make things done, feel free to find your best. Also, Zola provides their own mechanism to install and use themes, see [the docs](https://www.getzola.org/documentation/themes/installing-and-using-themes/). + +1. Fork the repo and replace demo-content inside content folder with yours. But take a look to _index.md files. It contains `title` and when you want to have anchor right of your headers add `insert_anchor_links = "right"` to each index. `theme.toml`, screenshot and readme may be deleted too. +2. Inside `config.toml` change URL and title on your own. In extra section you can specify path to your GitHub API for version below the logo on nav, favicon and logo itself. Or just remove the lines if you don't need it. Also, you can configure or turn on some additional settings related to Zola. [Specification is here](https://www.getzola.org/documentation/getting-started/configuration/). +3. In sass/_variables.scss you may change font, color or backgound if you want. +4. Almost done. Now, you should decide how you want to build and where will be hosted your website. You can build it locally and upload to somewhere. Or build in GitHub Actions and host on GitHub Pages / Netlify / CloudFlare Pages / AnyS3CloudStorage. [Howto for GitHub Pages](https://www.getzola.org/documentation/deployment/github-pages/). [My example](https://github.com/o365hq/o365hq.com/blob/main/.github/workflows/main.yml) of GitHub workflow with 2-steps build (the first checks for links and spelling errors, the second uploads to Azure). [Dockerfile](https://github.com/codeandmedia/zola_docsascode_theme/blob/master/Dockerfile) to make Docker image. + +Enjoy your docs! + +* _Icons: [Office UI Fabric Icons](https://uifabricicons.azurewebsites.net/)_ +* _Copy-code-button: [Aaron Luna](https://aaronluna.dev/blog/add-copy-button-to-code-blocks-hugo-chroma/)_ diff --git a/content/content/_index.md b/content/content/_index.md new file mode 100644 index 0000000..85ed62e --- /dev/null +++ b/content/content/_index.md @@ -0,0 +1,6 @@ ++++ +title = "Content" +weight = 2 +sort_by = "weight" +insert_anchor_links = "right" ++++ diff --git a/content/content/linking.md b/content/content/linking.md new file mode 100644 index 0000000..e8352e5 --- /dev/null +++ b/content/content/linking.md @@ -0,0 +1,55 @@ ++++ +title = "Internal links & deep linking" +weight = 50 ++++ + +## Heading id and anchor insertion +While rendering the Markdown content, a unique id will automatically be assigned to each heading. +This id is created by converting the heading text to a [slug](https://en.wikipedia.org/wiki/Semantic_URL#Slug) if `slugify.anchors` is set to `"on"` (the default). +If `slugify.paths` is set to `"safe"`, whitespaces are replaced by `_` and the following characters are stripped: `#`, `%`, `<`, `>`, `[`, `]`, `(`, `)`, \`, `^`, `{`, `|`, `}`. +If `slugify.paths` is set to `"off"`, no modifications are made, and you may be left with nominally illegal ids. +A number is appended at the end if the slug already exists for that article +For example: + +```md +# Something exciting! <- something-exciting +## Example code <- example-code + +# Something else <- something-else +## Example code <- example-code-1 +``` + +You can also manually specify an id with a `{#…}` suffix on the heading line: + +```md +# Something manual! {#manual} +``` + +This is useful for making deep links robust, either proactively (so that you can later change the text of a heading +without breaking links to it) or retroactively (keeping the slug of the old header text when changing the text). It +can also be useful for migration of existing sites with different header id schemes, so that you can keep deep +links working. + +## Anchor insertion +It is possible to have Zola automatically insert anchor links next to the heading, as you can see on this documentation +if you hover a title. + +This option is set at the section level: the `insert_anchor_links` variable on the +[section front matter page](@/content/section.md#front-matter). + +The default template is very basic and will need CSS tweaks in your project to look decent. +If you want to change the anchor template, it can be easily overwritten by +creating an `anchor-link.html` file in the `templates` directory. + +The anchor link template has the following variables: + +- `id`: the heading's id after applying the rules defined by `slugify.anchors` +- `level`: the heading level (between 1 and 6) + +## Internal links +Linking to other pages and their headings is so common that Zola adds a +special syntax to Markdown links to handle them: start the link with `@/` and point to the `.md` file you want +to link to. The path to the file starts from the `content` directory. + +For example, linking to a file located at `content/pages/about.md` would be `[my link](@/pages/about.md)`. +You can still link to an anchor directly; `[my link](@/pages/about.md#example)` will work as expected. diff --git a/content/content/multilingual.md b/content/content/multilingual.md new file mode 100644 index 0000000..cd697ff --- /dev/null +++ b/content/content/multilingual.md @@ -0,0 +1,44 @@ ++++ +title = "Multilingual sites" +weight = 130 ++++ + +Zola supports having a site in multiple languages. + +## Configuration +To get started, you will need to add the languages you want to support +to your `config.toml`. For example: + +```toml +languages = [ + {code = "fr", feed = true}, # there will be a feed for French content + {code = "fr", search = true}, # there will be a Search Index for French content + {code = "it"}, # there won't be a feed for Italian content +] +``` + +If you want to use per-language taxonomies, ensure you set the `lang` field in their +configuration. + +Note: By default, Chinese and Japanese search indexing is not included. You can include +the support by building `zola` using `cargo build --features search/indexing-ja search/indexing-zh`. +Please also note that, enabling Chinese indexing will increase the binary size by approximately +5 MB while enabling Japanese indexing will increase the binary size by approximately 70 MB +due to the incredibly large dictionaries. + +## Content +Once the languages have been added, you can start to translate your content. Zola +uses the filename to detect the language: + +- `content/an-article.md`: this will be the default language +- `content/an-article.fr.md`: this will be in French + +If the language code in the filename does not correspond to one of the languages or +the default language configured, an error will be shown. + +If your default language has an `_index.md` in a directory, you will need to add an `_index.{code}.md` +file with the desired front-matter options as there is no language fallback. + +## Output +Zola outputs the translated content with a base URL of `{base_url}/{code}/`. +The only exception to this is if you are setting a translated page `path` directly in the front matter. diff --git a/content/content/overview.md b/content/content/overview.md new file mode 100644 index 0000000..98b1d47 --- /dev/null +++ b/content/content/overview.md @@ -0,0 +1,117 @@ ++++ +title = "Overview" +weight = 10 ++++ + +Zola uses the directory structure to determine the site structure. +Each child directory in the `content` directory represents a [section](@/content/section.md) +that contains [pages](@/content/page.md) (your `.md` files). + +```bash +. +└── content + ├── content + │   └── something.md // -> https://mywebsite.com/content/something/ + ├── blog + │   ├── cli-usage.md // -> https://mywebsite.com/blog/cli-usage/ + │   ├── configuration.md // -> https://mywebsite.com/blog/configuration/ + │   ├── directory-structure.md // -> https://mywebsite.com/blog/directory-structure/ + │   ├── _index.md // -> https://mywebsite.com/blog/ + │   └── installation.md // -> https://mywebsite.com/blog/installation/ + └── landing + └── _index.md // -> https://mywebsite.com/landing/ +``` + +Each page path (the part after `base_url`, for example `blog/cli-usage/`) can be customised by changing the `path` or +`slug` attribute of the [page front-matter](@/content/page.md#front-matter). + +You might have noticed a file named `_index.md` in the example above. +This file is used to store both the metadata and content of the section itself and is not considered a page. + +To ensure that the terminology used in the rest of the documentation is understood, let's go over the example above. + +The `content` directory in this case has three `sections`: `content`, `blog` and `landing`. The `content` section has only +one page (`something.md`), the `landing` section has no pages and the `blog` section has 4 pages (`cli-usage.md`, +`configuration.md`, `directory-structure.md` and `installation.md`). + +Sections can be nested indefinitely. + +## Asset colocation + +The `content` directory is not limited to markup files. It's natural to want to co-locate a page and some related +assets, such as images or spreadsheets. Zola supports this pattern out of the box for both sections and pages. + +All non-Markdown files you add in a page/section directory will be copied alongside the generated page when the site is +built, which allows us to use a relative path to access them. + +Pages with co-located assets should not be placed directly in their section directory (such as `latest-experiment.md`), but +as an `index.md` file in a dedicated directory (`latest-experiment/index.md`), like so: + + +```bash +└── research + ├── latest-experiment + │ ├── index.md + │ └── yavascript.js + ├── _index.md + └── research.jpg +``` + +With this setup, you may access `research.jpg` from your 'research' section +and `yavascript.js` from your 'latest-experiment' page directly within the Markdown: + +```Markdown +Check out the complete program [here](yavascript.js). It's **really cool free-software**! +``` + +By default, this page's slug will be the directory name and thus its permalink will be `https://example.com/research/latest-experiment/`. + +### Excluding files from assets + +It is possible to ignore selected asset files using the +[ignored_content](@/getting-started/configuration.md) setting in the config file. +For example, say that you have an Excel spreadsheet from which you are taking several screenshots and +then linking to these image files on your website. For maintainability, you want to keep +the spreadsheet in the same directory as the Markdown file, but you don't want to copy the spreadsheet to +the public web site. You can achieve this by setting `ignored_content` in the config file: + +``` +ignored_content = ["*.xlsx"] +``` + +## Static assets + +In addition to placing content files in the `content` directory, you may also place content +files in the `static` directory. Any files/directories that you place in the `static` directory +will be copied, without modification, to the `public` directory. + +Typically, you might put site-wide assets (such as the site favicon, site logos or site-wide +JavaScript) in the root of the static directory. You can also place any HTML or other files that +you wish to be included without modification (that is, without being parsed as Markdown files) +into the static directory. + +Note that the static directory provides an _alternative_ to co-location. For example, imagine that you +had the following directory structure (a simplified version of the structure presented above): + +```bash +. +└── content + └── blog +    ├── configuration + │    └── index.md // -> https://mywebsite.com/blog/configuration/ +    └── _index.md // -> https://mywebsite.com/blog/ +``` + +To add an image to the `https://mywebsite.com/blog/configuration` page, you have three options: + * You could save the image to the `content/blog/configuration` directory and then link to it with a + relative path from the `index.md` page. This is the approach described under **co-location** + above. + * You could save the image to a `static/blog/configuration` directory and link to it in exactly the + same way as if you had co-located it. If you do this, the generated files will be identical to those + obtained if you had co-located the image; the only difference will be that all static files will be saved in the + static directory rather than in the content directory. The choice depends on your organizational needs. + * Or you could save the image to some arbitrary directory within the static directory. For example, + you could save all images to `static/images`. Using this approach, you can no longer use relative links. Instead, + you must use an absolute link to `images/[filename]` to access your + image. This might be preferable for small sites or for sites that associate images with + multiple pages (e.g., logo images that appear on every page). diff --git a/content/content/page.md b/content/content/page.md new file mode 100644 index 0000000..2038c50 --- /dev/null +++ b/content/content/page.md @@ -0,0 +1,154 @@ ++++ +title = "Page" +weight = 30 ++++ + +A page is any file ending with `.md` in the `content` directory, except files +named `_index.md`. + +If a file ending with `.md` is named `index.md`, it will generate a page +with the name of its directory (for example, `/content/about/index.md` would +create a page at `[base_url]/about`). (Note the lack of an underscore; if the file +were named `_index.md`, then it would create a **section** at `[base_url]/about`, as +discussed in a previous part of this documentation. In contrast, naming the file `index.md` will +create a **page** at `[base_url]/about`). + +If the file is given any name *other* than `index.md` or `_index.md`, then it will +create a page with that name (without the `.md`). For example, naming a file in the root of your +content directory `about.md` would create a page at `[base_url]/about`. +Another exception to this rule is that a filename starting with a datetime (YYYY-mm-dd or [an RFC3339 datetime](https://www.ietf.org/rfc/rfc3339.txt)) followed by +an underscore (`_`) or a dash (`-`) will use that date as the page date, unless already set +in the front matter. The page name will be anything after `_`/`-`, so the file `2018-10-10-hello-world.md` will +be available at `[base_url]/hello-world`. Note that the full RFC3339 datetime contains colons, which is not a valid +character in a filename on Windows. + +As you can see, creating an `about.md` file is equivalent to creating an +`about/index.md` file. The only difference between the two methods is that creating +the `about` directory allows you to use asset co-location, as discussed in the +[overview](@/content/overview.md#asset-colocation) section. + +## Output paths + +For any page within your content folder, its output path will be defined by either: + +- its `slug` frontmatter key +- its filename + +Either way, these proposed path will be sanitized before being used. +If `slugify.paths` is set to `"on"` in the site's config - the default - paths are [slugified](https://en.wikipedia.org/wiki/Clean_URL#Slug). +If it is set to `"safe"`, only sanitation is performed, with the following characters being removed: `<`, `>`, `:`, `/`, `|`, `?`, `*`, `#`, `\\`, `(`, `)`, `[`, `]` as well as newlines and tabulations. This ensures that the path can be represented on all operating systems. +Additionally, trailing whitespace and dots are removed and whitespaces are replaced by `_`. + +If `slugify.paths` is set to `"off"`, no modifications are made. + +If you want URLs containing non-ASCII characters, `slugify.paths` needs to be set to `"safe"` or `"off"`. + +### Path from frontmatter + +The output path for the page will first be read from the `slug` key in the page's frontmatter. + +**Example:** (file `content/zines/mlf-kurdistan.md`) + +``` ++++ +title = "Le mouvement des Femmes Libres, à la tête de la libération kurde" +slug = "femmes-libres-libération-kurde" ++++ +This is my article. +``` + +This frontmatter will output the article to `[base_url]/zines/femmes-libres-libération-kurde` with `slugify.paths` set to `"safe"` or `"off"`, and to `[base_url]/zines/femmes-libres-liberation-kurde` with the default value for `slugify.paths` of `"on"`. + +### Path from filename + +When the article's output path is not specified in the frontmatter, it is extracted from the file's path in the content folder. Consider a file `content/foo/bar/thing.md`. The output path is constructed: +- if the filename is `index.md`, its parent folder name (`bar`) is used as output path +- otherwise, the output path is extracted from `thing` (the filename without the `.md` extension) + +If the path found starts with a datetime string (`YYYY-mm-dd` or [a RFC3339 datetime](https://www.ietf.org/rfc/rfc3339.txt)) followed by an underscore (`_`) or a dash (`-`), this date is removed from the output path and will be used as the page date (unless already set in the front-matter). Note that the full RFC3339 datetime contains colons, which is not a valid character in a filename on Windows. + +The output path extracted from the file path is then slugified or not, depending on the `slugify.paths` config, as explained previously. + +**Example:** +The file `content/blog/2018-10-10-hello-world.md` will yield a page at `[base_url]/blog/hello-world`. + +## Front matter + +The TOML front matter is a set of metadata embedded in a file at the beginning of the file enclosed +by triple pluses (`+++`). + +Although none of the front matter variables are mandatory, the opening and closing `+++` are required. + +Note that even though the use of TOML is encouraged, YAML front matter is also supported to ease porting +legacy content. In this case the embedded metadata must be enclosed by triple minuses (`---`). + +Here is an example page with all the available variables. The values provided below are the +default values. + +```toml +title = "" +description = "" + +# The date of the post. +# Two formats are allowed: YYYY-MM-DD (2012-10-02) and RFC3339 (2002-10-02T15:00:00Z). +# Do not wrap dates in quotes; the line below only indicates that there is no default date. +# If the section variable `sort_by` is set to `date`, then any page that lacks a `date` +# will not be rendered. +# Setting this overrides a date set in the filename. +date = + +# The last updated date of the post, if different from the date. +# Same format as `date`. +updated = + +# The weight as defined on the Section page of the documentation. +# If the section variable `sort_by` is set to `weight`, then any page that lacks a `weight` +# will not be rendered. +weight = 0 + +# A draft page is only loaded if the `--drafts` flag is passed to `zola build`, `zola serve` or `zola check`. +draft = false + +# If set, this slug will be instead of the filename to make the URL. +# The section path will still be used. +slug = "" + +# The path the content will appear at. +# If set, it cannot be an empty string and will override both `slug` and the filename. +# The sections' path won't be used. +# It should not start with a `/` and the slash will be removed if it does. +path = "" + +# Use aliases if you are moving content but want to redirect previous URLs to the +# current one. This takes an array of paths, not URLs. +aliases = [] + +# When set to "true", the page will be in the search index. This is only used if +# `build_search_index` is set to "true" in the Zola configuration and the parent section +# hasn't set `in_search_index` to "false" in its front matter. +in_search_index = true + +# Template to use to render this page. +template = "page.html" + +# The taxonomies for this page. The keys need to be the same as the taxonomy +# names configured in `config.toml` and the values are an array of String objects. For example, +# tags = ["rust", "web"]. +[taxonomies] + +# Your own data. +[extra] +``` + +## Summary + +You can ask Zola to create a summary if, for example, you only want to show the first +paragraph of the page content in a list. + +To do so, add <!-- more --> in your content at the point +where you want the summary to end. The content up to that point will be +available separately in the +[template](@/templates/pages-sections.md#page-variables). + +A span element in this position with a `continue-reading` id is created, so you can link directly to it if needed. For example: +`Continue Reading`. diff --git a/content/content/sass.md b/content/content/sass.md new file mode 100644 index 0000000..8764467 --- /dev/null +++ b/content/content/sass.md @@ -0,0 +1,42 @@ ++++ +title = "Sass" +weight = 110 ++++ + +Sass is a popular CSS preprocessor that adds special features (e.g., variables, nested rules) to facilitate the +maintenance of large sets of CSS rules. If you're curious about what Sass +is and why it might be useful for styling your static site, the following links +may be of interest: + +* The [official Sass website](http://sass-lang.com/) +* [Why Sass?](https://alistapart.com/article/why-sass), by Dan Cederholm + +## Using Sass in Zola + +Zola processes any files with the `sass` or `scss` extension in the `sass` +folder, and places the processed output into a `css` file with the same folder +structure and base name into the `public` folder: + +```bash +. +└── sass + ├── style.scss // -> ./public/style.css + ├── indented_style.sass // -> ./public/indented_style.css + ├── _include.scss # This file won't get put into the `public` folder, but other files can @import it. + ├── assets + │ ├── fancy.scss // -> ./public/assets/fancy.css + │ ├── same_name.scss // -> ./public/assets/same_name.css + │ ├── same_name.sass # CONFLICT! This has the same base name as the file above, so Zola will return an error. + │ └── _common_mixins.scss # This file won't get put into the `public` folder, but other files can @import it. + └── secret-side-project + └── style.scss // -> ./public/secret-side-project/style.css +``` + +Files with a leading underscore in the name are not placed into the `public` +folder, but can still be used as `@import` dependencies. For more information, see the "Partials" section of +[Sass Basics](https://sass-lang.com/guide). + +Files with the `scss` extension use "Sassy CSS" syntax, +while files with the `sass` extension use the "indented" syntax: . +Zola will return an error if `scss` and `sass` files with the same +base name exist in the same folder to avoid confusion -- see the example above. diff --git a/content/content/search.md b/content/content/search.md new file mode 100644 index 0000000..d091105 --- /dev/null +++ b/content/content/search.md @@ -0,0 +1,26 @@ ++++ +title = "Search" +weight = 100 ++++ + +Zola can build a search index from the sections and pages content to +be used by a JavaScript library such as [elasticlunr](http://elasticlunr.com/). + +To enable it, you only need to set `build_search_index = true` in your `config.toml` and Zola will +generate an index for the `default_language` set for all pages not excluded from the search index. + +It is very important to set the `default_language` in your `config.toml` if you are writing a site not in +English; the index building pipelines are very different depending on the language. + +After `zola build` or `zola serve`, you should see two files in your static directory: + +- `search_index.${default_language}.js`: so `search_index.en.js` for a default setup +- `elasticlunr.min.js` + +As each site will be different, Zola makes no assumptions about your search function and doesn't provide +the JavaScript/CSS code to do an actual search and display results. You can look at how this site +implements it to get an idea: [search.js](https://github.com/getzola/zola/tree/master/docs/static/search.js). + +## Configuring the search index +In some cases, the default indexing strategy is not suitable. You can customise which fields to include and whether +to truncate the content in the [search configuration](@/getting-started/configuration.md). diff --git a/content/content/section.md b/content/content/section.md new file mode 100644 index 0000000..2951007 --- /dev/null +++ b/content/content/section.md @@ -0,0 +1,192 @@ ++++ +title = "Section" +weight = 20 ++++ + +A section is created whenever a directory (or subdirectory) in the `content` section contains an +`_index.md` file. If a directory does not contain an `_index.md` file, no section will be +created, but Markdown files within that directory will still create pages (known as orphan pages). + +The index page (i.e., the page displayed when a user browses to your `base_url`) is a section, +which is created whether or not you add an `_index.md` file at the root of your `content` directory. +If you do not create an `_index.md` file in your content directory, this main content section will +not have any content or metadata. If you would like to add content or metadata, you can add an +`_index.md` file at the root of the `content` directory and edit it just as you would edit any other +`_index.md` file; your `index.html` template will then have access to that content and metadata. + +Any non-Markdown file in a section directory is added to the `assets` collection of the section, as explained in the +[content overview](@/content/overview.md#asset-colocation). These files are then available in the +Markdown file using relative links. + +## Drafting +Just like pages sections can be drafted by setting the `draft` option in the front matter. By default this is not done. When a section is drafted it's descendants like pages, subsections and assets will not be processed unless the `--drafts` flag is passed. Note that even pages that don't have a `draft` status will not be processed if one of their parent sections is drafted. + +## Front matter + +The `_index.md` file within a directory defines the content and metadata for that section. To set +the metadata, add front matter to the file. + +The TOML front matter is a set of metadata embedded in a file at the beginning of the file enclosed by triple pluses (`+++`). + +After the closing `+++`, you can add content, which will be parsed as Markdown and made available +to your templates through the `section.content` variable. + +Although none of the front matter variables are mandatory, the opening and closing `+++` are required. + +Note that even though the use of TOML is encouraged, YAML front matter is also supported to ease porting +legacy content. In this case the embedded metadata must be enclosed by triple minuses (`---`). + +Here is an example `_index.md` with all the available variables. The values provided below are the +default values. + + +```toml +title = "" + +description = "" + +# A draft section is only loaded if the `--drafts` flag is passed to `zola build`, `zola serve` or `zola check`. +draft = false + +# Used to sort pages by "date", "weight" or "none". See below for more information. +sort_by = "none" + +# Used by the parent section to order its subsections. +# Lower values have higher priority. +weight = 0 + +# Template to use to render this section page. +template = "section.html" + +# The given template is applied to ALL pages below the section, recursively. +# If you have several nested sections, each with a page_template set, the page +# will always use the closest to itself. +# However, a page's own `template` variable will always have priority. +# Not set by default. +page_template = + +# This sets the number of pages to be displayed per paginated page. +# No pagination will happen if this isn't set or if the value is 0. +paginate_by = 0 + +# If set, this will be the path used by the paginated page. The page number will be appended after this path. +# The default is page/1. +paginate_path = "page" + +# This determines whether to insert a link for each header like the ones you can see on this site if you hover over +# a header. +# The default template can be overridden by creating an `anchor-link.html` file in the `templates` directory. +# This value can be "left", "right" or "none". +insert_anchor_links = "none" + +# If set to "true", the section pages will be in the search index. This is only used if +# `build_search_index` is set to "true" in the Zola configuration file. +in_search_index = true + +# If set to "true", the section homepage is rendered. +# Useful when the section is used to organize pages (not used directly). +render = true + +# This determines whether to redirect when a user lands on the section. Defaults to not being set. +# Useful for the same reason as `render` but when you don't want a 404 when +# landing on the root section page. +# Example: redirect_to = "documentation/content/overview" +redirect_to = + +# If set to "true", the section will pass its pages on to the parent section. Defaults to `false`. +# Useful when the section shouldn't split up the parent section, like +# sections for each year under a posts section. +transparent = false + +# Use aliases if you are moving content but want to redirect previous URLs to the +# current one. This takes an array of paths, not URLs. +aliases = [] + +# If set to "true", a feed file will be generated for this section at the +# section's root path. This is independent of the site-wide variable of the same +# name. The section feed will only include posts from that respective feed, and +# not from any other sections, including sub-sections under that section. +generate_feed = false + +# Your own data. +[extra] +``` + +Keep in mind that any configuration options apply only to the direct pages, not to the subsections' pages. + +## Pagination + +To enable pagination for a section's pages, set `paginate_by` to a positive number. See +[pagination template documentation](@/templates/pagination.md) for more information +on what variables are available in the template. + +You can also change the pagination path (the word displayed while paginated in the URL, like `page/1`) +by setting the `paginate_path` variable, which defaults to `page`. + +## Sorting +It is very common for Zola templates to iterate over pages or sections +to display all pages/sections in a given directory. Consider a very simple +example: a `blog` directory with three files: `blog/Post_1.md`, +`blog/Post_2.md` and `blog/Post_3.md`. To iterate over these posts and +create a list of links to the posts, a simple template might look like this: + +```j2 +{% for post in section.pages %} +

{{ post.title }}

+{% endfor %} +``` + +This would iterate over the posts in the order specified +by the `sort_by` variable set in the `_index.md` page for the corresponding +section. The `sort_by` variable can be given one of three values: `date`, +`weight` or `none`. If `sort_by` is not set, the pages will be +sorted in the `none` order, which is not intended for sorted content. + +Any page that is missing the data it needs to be sorted will be ignored and +won't be rendered. For example, if a page is missing the date variable and its +section sets `sort_by = "date"`, then that page will be ignored. +The terminal will warn you if this occurs. + +If several pages have the same date/weight/order, their permalink will be used +to break the tie based on alphabetical order. + +## Sorting pages +The `sort_by` front-matter variable can have the following values: + +### `date` +This will sort all pages by their `date` field, from the most recent (at the +top of the list) to the oldest (at the bottom of the list). Each page will +get `page.earlier` and `page.later` variables that contain the pages with +earlier and later dates, respectively. + +### `weight` +This will be sort all pages by their `weight` field, from lightest weight +(at the top of the list) to heaviest (at the bottom of the list). Each +page gets `page.lighter` and `page.heavier` variables that contain the +pages with lighter and heavier weights, respectively. + +### Reversed sorting +When iterating through pages, you may wish to use the Tera `reverse` filter, +which reverses the order of the pages. For example, after using the `reverse` filter, +pages sorted by weight will be sorted from lightest (at the top) to heaviest +(at the bottom); pages sorted by date will be sorted from oldest (at the top) +to newest (at the bottom). + +`reverse` has no effect on `page.later`/`page.earlier` or `page.heavier`/`page.lighter`. + +If the section is paginated the `paginate_reversed=true` in the front matter of the relevant section should be set instead of using the filter. + +## Sorting subsections +Sorting sections is a bit less flexible: sections can only be sorted by `weight`, +and do not have variables that point to the heavier/lighter sections. + +By default, the lightest (lowest `weight`) subsections will be at +the top of the list and the heaviest (highest `weight`) will be at the bottom; +the `reverse` filter reverses this order. + +**Note**: Unlike pages, permalinks will **not** be used to break ties between +equally weighted sections. Thus, if the `weight` variable for your section is not set (or if it +is set in a way that produces ties), then your sections will be sorted in +**random** order. Moreover, that order is determined at build time and will +change with each site rebuild. Thus, if there is any chance that you will +iterate over your sections, you should always assign them a weight. diff --git a/content/content/shortcodes.md b/content/content/shortcodes.md new file mode 100644 index 0000000..af90a02 --- /dev/null +++ b/content/content/shortcodes.md @@ -0,0 +1,243 @@ ++++ +title = "Shortcodes" +weight = 40 ++++ + +Zola borrows the concept of [shortcodes](https://codex.wordpress.org/Shortcode_API) from WordPress. +In our case, a shortcode corresponds to a template defined in the `templates/shortcodes` directory or +a built-in one that can be used in a Markdown file. If you want to use something similar to shortcodes in your templates, +try [Tera macros](https://tera.netlify.com/docs#macros). + +Broadly speaking, Zola's shortcodes cover two distinct use cases: + +* Inject more complex HTML: Markdown is good for writing, but it isn't great when you need add inline HTML or styling. +* Ease repetitive data based tasks: when you have [external data](@/templates/overview.md#load-data) that you + want to display in your page's body. + +The latter may also be solved by writing HTML, however Zola allows the use of Markdown based shortcodes which end in `.md` +rather than `.html`. This may be particularly useful if you want to include headings generated by the shortcode in the +[table of contents](@/content/table-of-contents.md). + +## Writing a shortcode +Let's write a shortcode to embed YouTube videos as an example. +In a file called `youtube.html` in the `templates/shortcodes` directory, paste the +following: + +```jinja2 +
+ +
+``` + +This template is very straightforward: an iframe pointing to the YouTube embed URL wrapped in a `
`. +In terms of input, this shortcode expects at least one variable: `id`. Because the other variables +are in an `if` statement, they are optional. + +That's it. Zola will now recognise this template as a shortcode named `youtube` (the filename minus the `.html` extension). + +The Markdown renderer will wrap an inline HTML node such as `` or `` into a paragraph. +If you want to disable this behaviour, wrap your shortcode in a `
`. + +A Markdown based shortcode in turn will be treated as if what it returned was part of the page's body. If we create +`books.md` in `templates/shortcodes` for example: + +```jinja2 +{% set data = load_data(path=path) -%} +{% for book in data.books %} +### {{ book.title }} + +{{ book.description | safe }} +{% endfor %} +``` + +This will create a shortcode `books` with the argument `path` pointing to a `.toml` file where it loads lists of books with +titles and descriptions. They will flow with the rest of the document in which `books` is called. + +Shortcodes are rendered before the page's Markdown is parsed so they don't have access to the page's table of contents. +Because of that, you also cannot use the `get_page`/`get_section`/`get_taxonomy` global functions. It might work while +running `zola serve` because it has been loaded but it will fail during `zola build`. + +## Using shortcodes + +There are two kinds of shortcodes: + +- ones that do not take a body, such as the YouTube example above +- ones that do, such as one that styles a quote + +In both cases, the arguments must be named and they will all be passed to the template. + +Lastly, a shortcode name (and thus the corresponding `.html` file) as well as the argument names +can only contain numbers, letters and underscores, or in Regex terms `[0-9A-Za-z_]`. +Although theoretically an argument name could be a number, it will not be possible to use such an argument in the template. + +Argument values can be of one of five types: + +- string: surrounded by double quotes, single quotes or backticks +- bool: `true` or `false` +- float: a number with a decimal point (e.g., 1.2) +- integer: a whole number or its negative counterpart (e.g., 3) +- array: an array of any kind of value, except arrays + +Malformed values will be silently ignored. + +Both types of shortcode will also get either a `page` or `section` variable depending on where they were used +and a `config` variable. These values will overwrite any arguments passed to a shortcode so these variable names +should not be used as argument names in shortcodes. + +### Shortcodes without body + +Simply call the shortcode as if it was a Tera function in a variable block. All the examples below are valid +calls of the YouTube shortcode. + +```md +Here is a YouTube video: + +{{/* youtube(id="dQw4w9WgXcQ") */}} + +{{/* youtube(id="dQw4w9WgXcQ", autoplay=true) */}} + +An inline {{/* youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") */}} shortcode +``` + +Note that if you want to have some content that looks like a shortcode but not have Zola try to render it, +you will need to escape it by using `{{/*` and `*/}}` instead of `{{` and `}}`. + +### Shortcodes with body +Let's imagine that we have the following shortcode `quote.html` template: + +```jinja2 +
+ {{ body }}
+ -- {{ author}} +
+``` + +We could use it in our Markdown file like so: + +```md +As someone said: + +{%/* quote(author="Vincent") */%} +A quote +{%/* end */%} +``` + +The body of the shortcode will be automatically passed down to the rendering context as the `body` variable and needs +to be on a new line. + +If you want to have some content that looks like a shortcode but not have Zola try to render it, +you will need to escape it by using `{%/*` and `*/%}` instead of `{%` and `%}`. You won't need to escape +anything else until the closing tag. + +### Invocation Count + +Every shortcode context is passed in a variable named `nth` that tracks how many times a particular shortcode has +been invoked in a Markdown file. Given a shortcode `true_statement.html` template: + +```jinja2 +

{{ value }} is equal to {{ nth }}.

+``` + +It could be used in our Markdown as follows: + +```md +{{/* true_statement(value=1) */}} +{{/* true_statement(value=2) */}} +``` + +This is useful when implementing custom markup for features such as sidenotes or end notes. + +## Built-in shortcodes + +Zola comes with a few built-in shortcodes. If you want to override a default shortcode template, +simply place a `{shortcode_name}.html` file in the `templates/shortcodes` directory and Zola will +use that instead. + +### YouTube +Embed a responsive player for a YouTube video. + +The arguments are: + +- `id`: the video id (mandatory) +- `class`: a class to add to the `
` surrounding the iframe +- `autoplay`: when set to "true", the video autoplays on load + +Usage example: + +```md +{{/* youtube(id="dQw4w9WgXcQ") */}} + +{{/* youtube(id="dQw4w9WgXcQ", autoplay=true) */}} + +{{/* youtube(id="dQw4w9WgXcQ", autoplay=true, class="youtube") */}} +``` + +Result example: + +{{ youtube(id="dQw4w9WgXcQ") }} + +### Vimeo +Embed a player for a Vimeo video. + +The arguments are: + +- `id`: the video id (mandatory) +- `class`: a class to add to the `
` surrounding the iframe + +Usage example: + +```md +{{/* vimeo(id="124313553") */}} + +{{/* vimeo(id="124313553", class="vimeo") */}} +``` + +Result example: + +{{ vimeo(id="124313553") }} + +### Streamable +Embed a player for a Streamable video. + +The arguments are: + +- `id`: the video id (mandatory) +- `class`: a class to add to the `
` surrounding the iframe + +Usage example: + +```md +{{/* streamable(id="92ok4") */}} + +{{/* streamable(id="92ok4", class="streamble") */}} +``` + +Result example: + +{{ streamable(id="92ok4") }} + +### Gist +Embed a [Github gist](https://gist.github.com). + +The arguments are: + +- `url`: the url to the gist (mandatory) +- `file`: by default, the shortcode will pull every file from the URL unless a specific filename is requested +- `class`: a class to add to the `
` surrounding the iframe + +Usage example: + +```md +{{/* gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57") */}} + +{{/* gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57", class="gist") */}} +``` + +Result example: + +{{ gist(url="https://gist.github.com/Keats/e5fb6aad409f28721c0ba14161644c57") }} diff --git a/content/content/syntax-highlighting.md b/content/content/syntax-highlighting.md new file mode 100644 index 0000000..b4f65da --- /dev/null +++ b/content/content/syntax-highlighting.md @@ -0,0 +1,171 @@ ++++ +title = "Syntax Highlighting" +weight = 80 ++++ + +Zola comes with built-in syntax highlighting but you first +need to enable it in the configuration + +Once this is done, Zola will automatically highlight all code blocks +in your content. A code block in Markdown looks like the following: + +````md + +```rust +let highlight = true; +``` + +```` + +You can replace `rust` with another language or not put anything to get the text +interpreted as plain text. + +Here is a full list of supported languages and their short names: + +``` +- ActionScript -> ["as"] +- Advanced CSV -> ["csv", "tsv"] +- AppleScript -> ["applescript", "script editor"] +- ASP -> ["asa"] +- Assembly x86 (NASM) -> ["asm", "inc", "nasm"] +- AWK -> ["awk"] +- Batch File -> ["bat", "cmd"] +- BibTeX -> ["bib"] +- Bourne Again Shell (bash) -> [".bash_aliases", ".bash_completions", ".bash_functions", ".bash_login", ".bash_logout", ".bash_profile", ".bash_variables", ".bashrc", ".ebuild", ".eclass", ".profile", ".textmate_init", ".zlogin", ".zlogout", ".zprofile", ".zshenv", ".zshrc", "PKGBUILD", "ash", "bash", "sh", "zsh"] +- C -> ["c", "h"] +- C# -> ["cs", "csx"] +- C++ -> ["C", "c++", "cc", "cp", "cpp", "cxx", "h", "h++", "hh", "hpp", "hxx", "inl", "ipp"] +- ClojureC -> ["boot", "clj", "cljc", "cljs", "cljx"] +- CMake -> ["CMakeLists.txt", "cmake"] +- CMake C Header -> ["h.in"] +- CMake C++ Header -> ["h++.in", "hh.in", "hpp.in", "hxx.in"] +- CMakeCache -> ["CMakeCache.txt"] +- Crystal -> ["cr"] +- CSS -> ["css", "css.erb", "css.liquid"] +- D -> ["d", "di"] +- Dart -> ["dart"] +- Diff -> ["diff", "patch"] +- Dockerfile -> ["Dockerfile", "dockerfile"] +- EDN -> ["edn"] +- Elixir -> ["ex", "exs"] +- Elm -> ["elm"] +- Erlang -> ["Emakefile", "emakefile", "erl", "escript", "hrl"] +- F# -> ["fs", "fsi", "fsx"] +- Fortran (Fixed Form) -> ["F", "F77", "FOR", "FPP", "f", "f77", "for", "fpp"] +- Fortran (Modern) -> ["F03", "F08", "F90", "F95", "f03", "f08", "f90", "f95"] +- Fortran Namelist -> ["namelist"] +- Friendly Interactive Shell (fish) -> ["fish"] +- GDScript (Godot Engine) -> ["gd"] +- Generic Config -> [".dircolors", ".gitattributes", ".gitignore", ".gitmodules", ".inputrc", "Doxyfile", "cfg", "conf", "config", "dircolors", "gitattributes", "gitignore", "gitmodules", "ini", "inputrc", "mak", "mk", "pro"] +- Git Attributes -> [".gitattributes", "attributes", "gitattributes"] +- Git Commit -> ["COMMIT_EDITMSG", "MERGE_MSG", "TAG_EDITMSG"] +- Git Config -> [".gitconfig", ".gitmodules", "gitconfig"] +- Git Ignore -> [".gitignore", "exclude", "gitignore"] +- Git Link -> [".git"] +- Git Log -> ["gitlog"] +- Git Mailmap -> [".mailmap", "mailmap"] +- Git Rebase Todo -> ["git-rebase-todo"] +- GLSL -> ["comp", "frag", "fs", "fsh", "fshader", "geom", "glsl", "gs", "gsh", "gshader", "tesc", "tese", "vert", "vs", "vsh", "vshader"] +- Go -> ["go"] +- GraphQL -> ["gql", "graphql", "graphqls"] +- Graphviz (DOT) -> ["DOT", "dot", "gv"] +- Groovy -> ["Jenkinsfile", "gradle", "groovy", "gvy"] +- Handlebars -> ["handlebars", "handlebars.html", "hbr", "hbrs", "hbs", "hdbs", "hjs", "mu", "mustache", "rac", "stache", "template", "tmpl"] +- Haskell -> ["hs"] +- HTML -> ["htm", "html", "shtml", "xhtml"] +- HTML (ASP) -> ["asp"] +- HTML (EEx) -> ["html.eex", "html.leex"] +- HTML (Erlang) -> ["yaws"] +- HTML (Jinja2) -> ["htm.j2", "html.j2", "xhtml.j2", "xml.j2"] +- HTML (Rails) -> ["erb", "html.erb", "rails", "rhtml"] +- HTML (Tcl) -> ["adp"] +- Java -> ["bsh", "java"] +- Java Properties -> ["properties"] +- Java Server Page (JSP) -> ["jsp"] +- JavaScript -> ["htc", "js"] +- JavaScript (Rails) -> ["js.erb"] +- Jinja2 -> ["j2", "jinja", "jinja2"] +- JSON -> ["Pipfile.lock", "ipynb", "json", "sublime-build", "sublime-color-scheme", "sublime-commands", "sublime-completions", "sublime-keymap", "sublime-macro", "sublime-menu", "sublime-mousemap", "sublime-project", "sublime-settings", "sublime-theme"] +- Julia -> ["jl"] +- Kotlin -> ["kt", "kts"] +- LaTeX -> ["ltx", "tex"] +- Less -> ["css.less", "less"] +- Linker Script -> ["ld"] +- Lisp -> ["cl", "clisp", "el", "fasl", "l", "lisp", "lsp", "mud", "scm", "ss"] +- Literate Haskell -> ["lhs"] +- lrc -> ["lrc", "lyric"] +- Lua -> ["lua"] +- Makefile -> ["GNUmakefile", "Makefile", "Makefile.am", "Makefile.in", "OCamlMakefile", "mak", "make", "makefile", "makefile.am", "makefile.in", "mk"] +- Markdown -> ["markdn", "markdown", "md", "mdown"] +- MATLAB -> ["matlab"] +- MiniZinc (MZN) -> ["dzn", "mzn"] +- NAnt Build File -> ["build"] +- Nim -> ["nim", "nims"] +- Nix -> ["nix"] +- Objective-C -> ["h", "m"] +- Objective-C++ -> ["M", "h", "mm"] +- OCaml -> ["ml", "mli"] +- OCamllex -> ["mll"] +- OCamlyacc -> ["mly"] +- Pascal -> ["dpr", "p", "pas"] +- Perl -> ["pc", "pl", "pm", "pmc", "pod", "t"] +- PHP -> ["php", "php3", "php4", "php5", "php7", "phps", "phpt", "phtml"] +- Plain Text -> ["txt"] +- PowerShell -> ["ps1", "psd1", "psm1"] +- PureScript -> ["purs"] +- Python -> ["SConscript", "SConstruct", "Sconstruct", "Snakefile", "bazel", "bzl", "cpy", "gyp", "gypi", "pxd", "pxd.in", "pxi", "pxi.in", "py", "py3", "pyi", "pyw", "pyx", "pyx.in", "rpy", "sconstruct", "vpy", "wscript"] +- R -> ["R", "Rprofile", "r"] +- Racket -> ["rkt"] +- Rd (R Documentation) -> ["rd"] +- Reason -> ["re", "rei"] +- Regular Expression -> ["re"] +- Regular Expressions (Elixir) -> ["ex.re"] +- reStructuredText -> ["rest", "rst"] +- Ruby -> ["Appfile", "Appraisals", "Berksfile", "Brewfile", "Cheffile", "Deliverfile", "Fastfile", "Gemfile", "Guardfile", "Podfile", "Rakefile", "Rantfile", "Scanfile", "Snapfile", "Thorfile", "Vagrantfile", "capfile", "cgi", "config.ru", "fcgi", "gemspec", "irbrc", "jbuilder", "podspec", "prawn", "rabl", "rake", "rb", "rbx", "rjs", "ruby.rail", "simplecov", "thor"] +- Ruby Haml -> ["haml", "sass"] +- Ruby on Rails -> ["builder", "rxml"] +- Rust -> ["rs"] +- Sass -> ["sass"] +- Scala -> ["sbt", "sc", "scala"] +- SCSS -> ["scss"] +- SQL -> ["ddl", "dml", "sql"] +- SQL (Rails) -> ["erbsql", "sql.erb"] +- srt -> ["srt", "subrip"] +- Stylus -> ["styl", "stylus"] +- SWI-Prolog -> ["pro"] +- Swift -> ["swift"] +- Tcl -> ["tcl"] +- TeX -> ["cls", "sty"] +- Textile -> ["textile"] +- TOML -> ["Cargo.lock", "Gopkg.lock", "Pipfile", "tml", "toml"] +- TypeScript -> ["ts"] +- TypeScriptReact -> ["tsx"] +- VimL -> ["vim"] +- XML -> ["dtml", "opml", "rng", "rss", "svg", "tld", "xml", "xsd", "xslt"] +- YAML -> ["sublime-syntax", "yaml", "yml"] +``` + +Note: due to some issues with the JavaScript syntax, the TypeScript syntax will be used instead. +If + +If you want to highlight a language not on this list, please open an issue or a pull request on the [Zola repo](https://github.com/getzola/zola). +Alternatively, the `extra_syntaxes` configuration option can be used to add additional syntax files. + +If your site source is laid out as follows: + +``` +. +├── config.toml +├── content/ +│   └── ... +├── static/ +│   └── ... +├── syntaxes/ +│   ├── Sublime-Language1/ +│   │   └── lang1.sublime-syntax +│   └── lang2.sublime-syntax +└── templates/ + └── ... +``` + +you would set your `extra_syntaxes` to `["syntaxes", "syntaxes/Sublime-Language1"]` to load `lang1.sublime-syntax` and `lang2.sublime-syntax`. diff --git a/content/content/table-of-contents.md b/content/content/table-of-contents.md new file mode 100644 index 0000000..d541d86 --- /dev/null +++ b/content/content/table-of-contents.md @@ -0,0 +1,36 @@ ++++ +title = "Table of Contents" +weight = 60 ++++ + +Each page/section will automatically generate a table of contents for itself based on the headers generated with markdown. + +It is available in the template through the `page.toc` or `section.toc` variable. +You can view the [template variables](@/templates/pages-sections.md#table-of-contents) +documentation for information on its structure. + +Here is an example of using that field to render a two-level table of contents: + +```jinja2 + +``` + +While headers are neatly ordered in this example, it will work just as well with disjoint headers. + +Note that all existing HTML tags from the title will NOT be present in the table of contents to +avoid various issues. diff --git a/content/content/taxonomies.md b/content/content/taxonomies.md new file mode 100644 index 0000000..39e78a0 --- /dev/null +++ b/content/content/taxonomies.md @@ -0,0 +1,138 @@ ++++ +title = "Taxonomies" +weight = 90 ++++ + +Zola has built-in support for taxonomies. Taxonomies are a way for users to group content according to user-defined categories. + +## Definitions + +- Taxonomy: A category that can be used to group content +- Term: A specific group within a taxonomy +- Value: A piece of content that can be associated with a term + +## Example: a movie website + +Imagine that you want to make a website to display information about various movies. In that case you could use the following taxonomies: + +- Director +- Genres +- Awards +- Release year + +Then at build time Zola can create pages for each taxonomy listing all of the known terms as well as pages for each term in a taxonomy, listing all of the pieces of content associated with that term. + +Imagine again we have the following movies: +``` +- Shape of water <--- Value + - Director <--- Taxonomy + - Guillermo Del Toro <--- Term + - Genres <--- Taxonomy + - Thriller <--- Term + - Drama <--- Term + - Awards <--- Taxonomy + - Golden globe <--- Term + - Academy award <--- Term + - BAFTA <--- Term + - Release year <--- Taxonomy + - 2017 <--- Term + +- The Room: <--- Value + - Director <--- Taxonomy + - Tommy Wiseau <--- Term + - Genres <--- Taxonomy + - Romance <--- Term + - Drama <--- Term + - Release Year <--- Taxonomy + - 2003 <--- Term + +- Bright <--- Value + - Director <--- Taxonomy + - David Ayer <--- Term + - Genres <--- Taxonomy + - Fantasy <--- Term + - Action <--- Term + - Awards <--- Taxonomy + - California on Location Awards <--- Term + - Release Year <--- Taxonomy + - 2017 <--- Term +``` + +In this example the page for `Release year` would include links to pages for both 2003 and 2017, where the page for 2017 would list both Shape of Water and Bright. + +## Configuration + +A taxonomy has five variables: + +- `name`: a required string that will be used in the URLs, usually the plural version (i.e., tags, categories, etc.) +- `paginate_by`: if this is set to a number, each term page will be paginated by this much. +- `paginate_path`: if set, this path will be used by the paginated page and the page number will be appended after it. +For example the default would be page/1. +- `feed`: if set to `true`, a feed (atom by default) will be generated for each term. +- `lang`: only set this if you are making a multilingual site and want to indicate which language this taxonomy is for + +Insert into the configuration file (config.toml): + +⚠️ Place the taxonomies key in the main section and not in the `[extra]` section + +**Example 1:** (one language) + +```toml +taxonomies = [ + { name = "director", feed = true}, + { name = "genres", feed = true}, + { name = "awards", feed = true}, + { name = "release-year", feed = true}, +] +``` + +**Example 2:** (multilingual site) + +```toml +taxonomies = [ + {name = "director", feed = true, lang = "fr"}, + {name = "director", feed = true, lang = "eo"}, + {name = "director", feed = true, lang = "en"}, + {name = "genres", feed = true, lang = "fr"}, + {name = "genres", feed = true, lang = "eo"}, + {name = "genres", feed = true, lang = "en"}, + {name = "awards", feed = true, lang = "fr"}, + {name = "awards", feed = true, lang = "eo"}, + {name = "awards", feed = true, lang = "en"}, + {name = "release-year", feed = true, lang = "fr"}, + {name = "release-year", feed = true, lang = "eo"}, + {name = "release-year", feed = true, lang = "en"}, +] +``` + +## Using taxonomies + +Once the configuration is done, you can then set taxonomies in your content and Zola will pick them up: + +**Example:** + +```toml ++++ +title = "Shape of water" +date = 2019-08-15 # date of the post, not the movie +[taxonomies] +director=["Guillermo Del Toro"] +genres=["Thriller","Drama"] +awards=["Golden Globe", "Academy award", "BAFTA"] +release-year = ["2017"] ++++ +``` + +## Output paths + +In a similar manner to how section and pages calculate their output path: +- the taxonomy name is never slugified +- the taxonomy term (e.g. as specific tag) is slugified when `slugify.taxonomies` is enabled (`"on"`, the default) in the configuration + +The taxonomy pages are then available at the following paths: + +```plain +$BASE_URL/$NAME/ (taxonomy) +$BASE_URL/$NAME/$SLUG (taxonomy entry) +``` +Note that taxonomies are case insensitive so terms that have the same slug will get merged, e.g. sections and pages containing the tag "example" will be shown in the same taxonomy page as ones containing "Example" diff --git a/content/deployment/_index.md b/content/deployment/_index.md new file mode 100644 index 0000000..c5f27ac --- /dev/null +++ b/content/deployment/_index.md @@ -0,0 +1,6 @@ ++++ +title = "Deployment" +weight = 5 +sort_by = "weight" ++++ + diff --git a/content/deployment/github-pages.md b/content/deployment/github-pages.md new file mode 100644 index 0000000..437f9d3 --- /dev/null +++ b/content/deployment/github-pages.md @@ -0,0 +1,120 @@ ++++ +title = "GitHub Pages" +weight = 30 ++++ + +By default, GitHub Pages uses Jekyll (a ruby based static site generator), +but you can also publish any generated files provided you have an `index.html` file in the root of a branch called +`gh-pages` or `master`. In addition you can publish from a `docs` directory in your repository. That branch name can +also be manually changed in the settings of a repository. + +We can use any continuous integration (CI) server to build and deploy our site. For example: + + * [Github Actions](#github-actions) + * [Travis CI](#travis-ci) + +## Github Actions + +Using *Github Actions* for the deployment of your Zola-Page on Github-Pages is pretty easy. You basically need three things: + +1. A *Personal access token* to give the *Github Action* the permission to push into your repository. +2. Create the *Github Action*. +3. Check the *Github Pages* section in repository settings. + +Let's start with the token. + +For creating the token either click on [here](https://github.com/settings/tokens) or go to Settings > Developer Settings > Personal access tokens. Under the *Select Scopes* section, give it *repo* permissions and click *Generate token*. Then copy the token, navigate to your repository and add in the Settings tab the *Secret* `TOKEN` and paste your token in it. + +Next we need to create the *Github Action*. Here we can make use of the [zola-deploy-action](https://github.com/shalzz/zola-deploy-action). Go to the *Actions* tab of your repository, click on *set up a workflow yourself* to get a blank workflow file. Copy the following script into it and commit it afterwards. + +```yaml +# On every push this script is executed +on: push +name: Build and deploy GH Pages +jobs: + build: + name: shalzz/zola-deploy-action + runs-on: ubuntu-latest + steps: + # Checkout + - uses: actions/checkout@master + # Build & deploy + - name: shalzz/zola-deploy-action + uses: shalzz/zola-deploy-action@v0.12.0 + env: + # Target branch + PAGES_BRANCH: gh-pages + # Provide personal access token + TOKEN: ${{ secrets.TOKEN }} +``` + +This script is pretty simple, because the [zola-deploy-action](https://github.com/shalzz/zola-deploy-action) is doing everything for you. You just need to provide some details. For more configuration options check out the [README](https://github.com/shalzz/zola-deploy-action/blob/master/README.md). + +By commiting the action your first build is triggered. Wait until it's finished, then you should see in your repository a new branch *gh-pages* with the compiled *Zola* page in it. + +Finally we need to check the *Github Pages* section of the repository settings. Click on the *Settings* tab and scroll down to the *Github Pages* section. Check if the source is set to *gh-pages* branch and the directory is */ (root)*. You should also see your *Github Pages* link. + +There you can also configure a *custom domain* and *Enforce HTTPS* mode. Before configuring a *custom domains*, please check out [this](https://github.com/shalzz/zola-deploy-action/blob/master/README.md#custom-domain). + +## Travis CI + +We are going to use [Travis CI](https://travis-ci.org) to automatically publish the site. If you are not using Travis +already, you will need to login with the GitHub OAuth and activate Travis for the repository. +Don't forget to also check if your repository allows GitHub Pages in its settings. + +## Ensure that Travis can access your theme + +Depending on how you added your theme, Travis may not know how to access +it. The best way to ensure that it will have full access to the theme is to use git +submodules. When doing this, ensure that you are using the `https` version of the URL. + +```shell +$ git submodule add {THEME_URL} themes/{THEME_NAME} +``` + +## Allowing Travis to push to GitHub + +Before pushing anything, Travis needs a Github private access key to make changes to your repository. +If you're already logged in to your account, just click [here](https://github.com/settings/tokens) to go to +your tokens page. +Otherwise, navigate to `Settings > Developer Settings > Personal Access Tokens`. +Generate a new token and give it any description you'd like. +Under the "Select Scopes" section, give it repo permissions. Click "Generate token" to finish up. + +Your token will now be visible. +Copy it into your clipboard and head back to Travis. +Once on Travis, click on your project, and navigate to "Settings". Scroll down to "Environment Variables" and input a name of `GH_TOKEN` with a value of your access token. +Make sure that "Display value in build log" is off, and then click add. Now Travis has access to your repository. + +## Setting up Travis + +We're almost done. We just need some scripts in a .travis.yml file to tell Travis what to do. + +**NOTE**: The script below assumes that we're taking the code from the `code` branch and will generate the HTML to be published in the `master` branch of the same repository. You're free to use any other branch for the Markdown files but if you want to use `.github.io` or `.github.io`, the destination branch **MUST** be `master`. + +```yaml +language: minimal + +before_script: + # Download and unzip the zola executable + # Replace the version numbers in the URL by the version you want to use + - curl -s -L https://github.com/getzola/zola/releases/download/v0.9.0/zola-v0.9.0-x86_64-unknown-linux-gnu.tar.gz | sudo tar xvzf - -C /usr/local/bin + +script: + - zola build + +# If you are using a different folder than `public` for the output directory, you will +# need to change the `zola` command and the `ghp-import` path +after_success: | + [ $TRAVIS_BRANCH = code ] && + [ $TRAVIS_PULL_REQUEST = false ] && + zola build && + sudo pip install ghp-import && + ghp-import -n public -b master && + git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git master +``` + +If your site is using a custom domain, you will need to mention it in the `ghp-import` command: +`ghp-import -c vaporsoft.net -n public` for example. + +Credits: this page is based on the article https://vaporsoft.net/publishing-gutenberg-to-github/ diff --git a/content/deployment/gitlab-pages.md b/content/deployment/gitlab-pages.md new file mode 100644 index 0000000..933eeeb --- /dev/null +++ b/content/deployment/gitlab-pages.md @@ -0,0 +1,71 @@ ++++ +title = "GitLab Pages" +weight = 40 ++++ + +We are going to use the GitLab CI runner to automatically publish the site (this CI runner is already included in your repository if you use GitLab.com). + +## Repository setup + +Your repository needs to be set up to be a user or group website. This means the name of the repository has to be in the correct format. + +For example, assuming that the username is `john`, you have to create a project called `john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`. Once you enable GitLab Pages for your project, your website will be published under `https://john.gitlab.io`. + +Under your group `websites`, you created a project called `websites.gitlab.io`. Your project’s URL will be `https://gitlab.com/websites/websites.gitlab.io`. Once you enable GitLab Pages for your project, your website will be published under `https://websites.gitlab.io`. + + +This guide assumes that your Zola project is located in the root of your repository. + +## Ensuring that the CI runner can access your theme + +Depending on how you added your theme, your repository may not contain it. The best way to ensure that the theme will +be added is to use submodules. When doing this, ensure that you are using the `https` version of the URL. + +```shell +$ git submodule add {THEME_URL} themes/{THEME_NAME} +``` + +For example, this could look like: +```shell +$ git submodule add https://github.com/getzola/hyde.git themes/hyde +``` + +## Setting up the GitLab CI/CD Runner + +The second step is to tell the GitLab continuous integration runner how to create the GitLab page. + +To do this, create a file called `.gitlab-ci.yml` in the root directory of your repository. + +```yaml +image: alpine:latest +variables: + # This variable will ensure that the CI runner pulls in your theme from the submodule + GIT_SUBMODULE_STRATEGY: recursive + # Specify the zola version you want to use here + ZOLA_VERSION: "v0.12.0" + +pages: + script: + # Install the zola package from the alpine community repositories + - apk add --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community/ zola + # Execute zola build + - zola build + + artifacts: + paths: + # Path of our artifacts + - public + + # This config will only publish changes that are pushed on the master branch + only: + - master +``` + +Push this new file and ... Tada! You're done! If you navigate to `settings > pages`, you should be able to see +something like this: + +> Congratulations! Your pages are served under: +https://john.gitlab.io + +More information on the process to host on GitLab pages and additional information like using a custom domain is documented +[in this GitLab blog post](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/). diff --git a/content/deployment/netlify.md b/content/deployment/netlify.md new file mode 100644 index 0000000..6402991 --- /dev/null +++ b/content/deployment/netlify.md @@ -0,0 +1,70 @@ ++++ +title = "Netlify" +weight = 20 ++++ + +Netlify provides best practices like SSL, CDN distribution, caching and continuous deployment +with no effort. This site is hosted by Netlify and automatically deployed on commits. + +If you don't have an account with Netlify, you can [sign up](https://app.netlify.com) for one. + + +## Automatic deploys + +Once you are in the admin interface, you can add a site from a Git provider (GitHub, GitLab or Bitbucket). At the end + of this process, you can select the deploy settings for the project: + + - build command: `zola build` (replace the version number in the variable by the version you want to use) + - publish directory: the path to where the `public` directory is + - image selection: `Ubuntu Xenial 16.04 (default)` + - Environment variables: `ZOLA_VERSION` with for example `0.8.0` as value + +With this setup, your site should be automatically deployed on every commit on master. For `ZOLA_VERSION`, you may +use any of the tagged `release` versions in the GitHub repository. Netlify will automatically fetch the tagged version +and use it to build your site. + +However, if you want to use everything that Netlify gives you, you should also publish temporary sites for pull requests. + +This is done by adding the following `netlify.toml` file in your repository and removing the build command/publish +directory in the admin interface. + +```toml +[build] +# This assumes that the Zola site is in a docs folder. If it isn't, you don't need +# to have a `base` variable but you do need the `publish` and `command` variables. +base = "docs" +publish = "docs/public" +command = "zola build" + +[build.environment] +# Set the version name that you want to use and Netlify will automatically use it. +ZOLA_VERSION = "0.9.0" + +# The magic for deploying previews of branches. +# We need to override the base url with whatever url Netlify assigns to our +# preview site. We do this using the Netlify environment variable +# `$DEPLOY_PRIME_URL`. + +[context.deploy-preview] +command = "zola build --base-url $DEPLOY_PRIME_URL" +``` + +## Manual deploys +If you would prefer to use a version of Zola that isn't a tagged release (for example, after having built Zola from +source and made modifications), then you will need to manually deploy your `public` folder to Netlify. You can do +this through Netlify's web GUI or via the command line. + +For a command-line manual deploy, follow these steps: + 1. Generate a `Personal Access Token` from the settings section of your Netlify account (*not* an OAuth Application). + 2. Build your site with `zola build`. + 3. Create a zip folder containing the `public` directory. + 4. Run the `curl` command below, filling in your values for PERSONAL_ACCESS_TOKEN_FROM_STEP_1, FILE_NAME.zip + and SITE_NAME. + 5. (Optional) delete the zip folder. + +```bash +curl -H "Content-Type: application/zip" \ + -H "Authorization: Bearer PERSONAL_ACCESS_TOKEN_FROM_STEP_1" \ + --data-binary "@FILE_NAME.zip" \ + https://api.netlify.com/api/v1/sites/SITE_NAME.netlify.com/deploys +``` diff --git a/content/deployment/overview.md b/content/deployment/overview.md new file mode 100644 index 0000000..0eba0af --- /dev/null +++ b/content/deployment/overview.md @@ -0,0 +1,9 @@ ++++ +title = "Overview" +weight = 10 ++++ + +Zola outputs plain files, no databases needed. This makes hosting and deployment +trivial on many providers. + + diff --git a/content/deployment/vercel.md b/content/deployment/vercel.md new file mode 100644 index 0000000..66f5d43 --- /dev/null +++ b/content/deployment/vercel.md @@ -0,0 +1,36 @@ ++++ +title = "Vercel" +weight = 50 ++++ + +Vercel (previously zeit) is similar to Netlify, making deployment of sites easy. +The sites are hosted by Vercel and automatically deployed whenever we push a +commit to our selected production branch (e.g, master). + +If you don't have an account with Vercel, you can sign up [here](https://vercel.com/signup). + +## Automatic deploys + +Once you sign up you can import your site from a Git provider (Github, GitLab or Bitbucket). +After the import, you can set the settings for your project. + +- Choose Framework Preset as **Other** +- Build command as `zola build` and make sure toggle on Override switch. +- By default Vercel chooses output directory as `public`, if you use a different directory then specify output directory. +- To add your own domain, go to domain setting in left and add it there. + + +All we have to is include a `vercel.json` in our project's root directory by +specifying the `ZOLA_VERSION` we want to use to deploy the site. + +``` + { + "build": { + "env": { + "ZOLA_VERSION": "0.12.0" + } + } +} +``` + +And your site should now be up and running. diff --git a/content/getting-started/_index.md b/content/getting-started/_index.md new file mode 100644 index 0000000..0acd709 --- /dev/null +++ b/content/getting-started/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Getting Started" +weight = 1 +sort_by = "weight" ++++ diff --git a/content/getting-started/cli-usage.md b/content/getting-started/cli-usage.md new file mode 100644 index 0000000..1cc25dd --- /dev/null +++ b/content/getting-started/cli-usage.md @@ -0,0 +1,129 @@ ++++ +title = "CLI usage" +weight = 15 ++++ + +Zola only has 4 commands: `init`, `build`, `serve` and `check`. + +You can view the help for the whole program by running `zola --help` and +that for a specific command by running `zola --help`. + +## init + +Creates the directory structure used by Zola at the given directory after asking a few basic configuration questions. +Any choices made during these prompts can be easily changed by modifying `config.toml`. + +```bash +$ zola init my_site +$ zola init +``` + +If the `my_site` directory already exists, Zola will only populate it if it contains only hidden files (dotfiles are ignored). If no `my_site` argument is passed, Zola will try to populate the current directory. + +In case you want to attempt to populate a non-empty directory and are brave, you can use `zola init --force`. Note that this will _not_ overwrite existing folders or files; in those cases you will get a `File exists (os error 17)` error or similar. + +You can initialize a git repository and a Zola site directly from within a new folder: + +```bash +$ git init +$ zola init +``` + +## build + +This will build the whole site in the `public` directory (if this directory already exists, it is overwritten). + +```bash +$ zola build +``` + +You can override the config `base_url` by passing a new URL to the `base-url` flag. + +```bash +$ 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 +deploy previews. + +You can override the default output directory `public` by passing another value to the `output-dir` flag. + +```bash +$ zola build --output-dir $DOCUMENT_ROOT +``` + +You can point to a config file other than `config.toml` like so (note that the position of the `config` option is important): + +```bash +$ zola --config config.staging.toml build +``` + +You can also process a project from a different directory with the `root` flag. If building a project 'out-of-tree' with the `root` flag, you may want to combine it with the `output-dir` flag. (Note that like `config`, the position is important): +```bash +$ zola --root /path/to/project build +``` + +By default, 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 +the interface/port combination to use if you want something different than the default (`127.0.0.1:1111`). + +You can also specify different addresses for the interface and base_url using `--interface` and `-u`/`--base-url`, respectively, if for example you are running Zola in a Docker container. + +Use the `--open` flag to automatically open the locally hosted instance in your +web browser. + +In the event you don't want Zola to run a local web server, you can use the `--watch-only` flag. + +Before starting, Zola will delete the `public` directory to start from a clean slate. + +```bash +$ zola serve +$ zola serve --port 2000 +$ zola serve --interface 0.0.0.0 +$ 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 --port 2000 --output-dir www/public +$ zola serve --watch-only +$ zola serve --open +``` + +The serve command will watch all your content and provide live reload without +a hard refresh if possible. + +Some changes cannot be handled automatically and thus live reload may not always work. If you +fail to see your change or get an error, try restarting `zola serve`. + + +You can also point to a config file other than `config.toml` like so (note that the position of the `config` option is important): + +```bash +$ zola --config config.staging.toml serve +``` + +By default, 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 in Markdown files by trying to fetch +them (links in the template files are not checked). + +By default, drafts are not loaded. If you wish to include them, pass the `--drafts` flag. + +## Colored output + +Colored output is used if your terminal supports it. + +*Note*: coloring is automatically disabled when the output is redirected to a pipe or a file (i.e., when the standard output is not a TTY). + +You can disable this behavior by exporting one of the following two environment variables: + +- `NO_COLOR` (the value does not matter) +- `CLICOLOR=0` + +To force the use of colors, you can set the following environment variable: + +- `CLICOLOR_FORCE=1` diff --git a/content/getting-started/configuration.md b/content/getting-started/configuration.md new file mode 100644 index 0000000..b97fd5b --- /dev/null +++ b/content/getting-started/configuration.md @@ -0,0 +1,245 @@ ++++ +title = "Configuration" +weight = 40 ++++ + +The default configuration is sufficient to get Zola running locally but not more than that. +It follows the philosophy of paying for only what you need, almost everything is turned off by default. + +To change the configuration, edit the `config.toml` file. +If you are not familiar with TOML, have a look at [the TOML spec](https://github.com/toml-lang/toml). + +⚠️ If you add keys to your `config.toml`, you must pay attention to which TOML section it belongs to. + +Here are the current `config.toml` sections: +1. main (unnamed) +2. link_checker +3. slugify +4. search +5. translations +6. extra + +**Only the `base_url` variable is mandatory**. Everything else is optional. All configuration variables +used by Zola as well as their default values are listed below: + +```toml +# The base URL of the site; the only required configuration variable. +base_url = "mywebsite.com" + +# The site title and description; used in feeds by default. +title = "" +description = "" + +# The default language; used in feeds. +default_language = "en" + +# The site theme to use. +theme = "" + +# When set to "true", a feed is automatically generated. +generate_feed = false + +# The filename to use for the feed. Used as the template filename, too. +# Defaults to "atom.xml", which has a built-in template that renders an Atom 1.0 feed. +# There is also a built-in template "rss.xml" that renders an RSS 2.0 feed. +# feed_filename = "atom.xml" + +# The number of articles to include in the feed. All items are included if +# this limit is not set (the default). +# feed_limit = 20 + +# When set to "true", files in the `static` directory are hard-linked. Useful for large +# static files. Note that for this to work, both `static` and the +# output directory need to be on the same filesystem. Note that the theme's `static` +# files are always copied, regardless of this setting. +# hard_link_static = false + +# The taxonomies to be rendered for the site and their configuration. +# Example: +# taxonomies = [ +# {name = "tags", feed = true}, # each tag will have its own feed +# {name = "tags", lang = "fr"}, # you can have taxonomies with the same name in multiple languages +# {name = "categories", paginate_by = 5}, # 5 items per page for a term +# {name = "authors"}, # Basic definition: no feed or pagination +# ] +# +taxonomies = [] + +# The additional languages for the site. +# Example: +# languages = [ +# {code = "fr", feed = true}, # there will be a feed for French content +# {code = "fr", search = true}, # there will be a Search Index for French content +# {code = "it"}, # there won't be a feed for Italian content +# ] +# +languages = [] + +# When set to "true", the Sass files in the `sass` directory in the site root are compiled. +# Sass files in theme directories are always compiled. +compile_sass = false + +# When set to "true", the generated HTML files are minified. +minify_html = false + +# A list of glob patterns specifying asset files to ignore when the content +# directory is processed. Defaults to none, which means that all asset files are +# copied over to the `public` directory. +# Example: +# ignored_content = ["*.{graphml,xlsx}", "temp.*"] +ignored_content = [] + +# A list of directories used to search for additional `.sublime-syntax` files. +extra_syntaxes = [] + +# You can override the default output directory `public` by setting an another value. +# output_dir = "docs" + +# Configuration of the Markdown rendering +[markdown] +# When set to "true", all code blocks are highlighted. +highlight_code = false + +# The theme to use for code highlighting. +# See below for list of allowed values. +highlight_theme = "base16-ocean-dark" + +# When set to "true", emoji aliases translated to their corresponding +# Unicode emoji equivalent in the rendered Markdown files. (e.g.: :smile: => 😄) +render_emoji = false + +# Whether external links are to be opened in a new tab +# If this is true, a `rel="noopener"` will always automatically be added for security reasons +external_links_target_blank = false + +# Whether to set rel="nofollow" for all external links +external_links_no_follow = false + +# Whether to set rel="noreferrer" for all external links +external_links_no_referrer = false + +# Whether smart punctuation is enabled (changing quotes, dashes, dots in their typographic form) +# For example, `...` into `…`, `"quote"` into `“curly”` etc +smart_punctuation = false + +# Configuration of the link checker. +[link_checker] +# Skip link checking for external URLs that start with these prefixes +skip_prefixes = [ + "http://[2001:db8::]/", +] + +# Skip anchor checking for external URLs that start with these prefixes +skip_anchor_prefixes = [ + "https://caniuse.com/", +] + +# Various slugification strategies, see below for details +# Defaults to everything being a slug +[slugify] +paths = "on" +taxonomies = "on" +anchors = "on" + +# When set to "true", a search index is built from the pages and section +# content for `default_language`. +build_search_index = false + +[search] +# Whether to include the title of the page/section in the index +include_title = true +# Whether to include the description of the page/section in the index +include_description = false +# Whether to include the rendered content of the page/section in the index +include_content = true +# At which character to truncate the content to. Useful if you have a lot of pages and the index would +# become too big to load on the site. Defaults to not being set. +# truncate_content_length = 100 + +# Optional translation object. Keys should be language codes. +# Optional translation object. The key if present should be a language code. +# Example: +# default_language = "fr" +# +# [translations] +# [translations.fr] +# title = "Un titre" +# +# [translations.en] +# title = "A title" +# +[translations] + +# You can put any kind of data here. The data +# will be accessible in all templates +# Example: +# [extra] +# author = "Famous author" +# +# author value will be available using {{ config.extra.author }} in templates +# +[extra] +``` + +## Syntax highlighting + +Zola currently has the following highlight themes available: + +- [1337](https://tmtheme-editor.herokuapp.com/#!/editor/theme/1337) +- [agola-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Agola%20Dark) +- [ascetic-white](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Ascetic%20White) +- [axar](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Axar) +- [ayu-dark](https://github.com/dempfi/ayu) +- [ayu-light](https://github.com/dempfi/ayu) +- [ayu-mirage](https://github.com/dempfi/ayu) +- [base16-ocean-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Base16%20Ocean%20Dark) +- [base16-ocean-light](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Base16%20Ocean%20Light) +- [bbedit](https://tmtheme-editor.herokuapp.com/#!/editor/theme/BBEdit) +- [boron](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Boron) +- [charcoal](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Charcoal) +- [cheerfully-light](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Cheerfully%20Light) +- [classic-modified](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Classic%20Modified) +- [demain](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Demain) +- [dimmed-fluid](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Dimmed%20Fluid) +- [dracula](https://draculatheme.com/) +- [gray-matter-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Gray%20Matter%20Dark) +- [gruvbox-dark](https://github.com/morhetz/gruvbox) +- [gruvbox-light](https://github.com/morhetz/gruvbox) +- [idle](https://tmtheme-editor.herokuapp.com/#!/editor/theme/IDLE) +- [inspired-github](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Inspiredgithub) +- [ir-white](https://tmtheme-editor.herokuapp.com/#!/editor/theme/IR_White) +- [kronuz](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Kronuz) +- [material-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Material%20Dark) +- [material-light](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Material%20Light) +- [monokai](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Monokai) +- [nord](https://github.com/crabique/Nord-plist/tree/0d655b23d6b300e691676d9b90a68d92b267f7ec) +- [nyx-bold](https://github.com/GalAster/vscode-theme-nyx) +- [one-dark](https://github.com/andresmichel/one-dark-theme) +- [OneHalf](https://github.com/sonph/onehalf) +- [solarized-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Solarized%20(dark)) +- [solarized-light](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Solarized%20(light)) +- [subway-madrid](https://github.com/idleberg/Subway.tmTheme) +- [subway-moscow](https://github.com/idleberg/Subway.tmTheme) +- [Tomorrow](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Tomorrow) +- [TwoDark](https://github.com/erremauro/TwoDark) +- [visual-studio-dark](https://tmtheme-editor.herokuapp.com/#!/editor/theme/Visual%20Studio%20Dark) +- [zenburn](https://github.com/colinta/zenburn) + +Zola uses the Sublime Text themes, making it very easy to add more. +If you want a theme not listed above, please open an issue or a pull request on the [Zola repo](https://github.com/getzola/zola). + +## Slugification strategies + +By default, Zola will turn every path, taxonomies and anchors to a slug, an ASCII representation with no special characters. +You can however change that strategy for each kind of item, if you want UTF-8 characters in your URLs for example. There are 3 strategies: + +- `on`: the default one, everything is turned into a slug +- `safe`: characters that cannot exist in files on Windows (`<>:"/\|?*`) or Unix (`/`) are removed, everything else stays +- `off`: nothing is changed, your site might not build on some OS and/or break various URL parsers + +Since there are no filename issues with anchors, the `safe` and `off` strategies are identical in their case: the only change +is space being replaced by `_` since a space is not valid in an anchor. + +Note that if you are using a strategy other than the default, you will have to manually escape whitespace and Markdown +tokens to be able to link to your pages. For example an internal link to a file named `some space.md` will need to be +written like `some%20space.md` in your Markdown files. diff --git a/content/getting-started/directory-structure.md b/content/getting-started/directory-structure.md new file mode 100644 index 0000000..f00c221 --- /dev/null +++ b/content/getting-started/directory-structure.md @@ -0,0 +1,51 @@ ++++ +title = "Directory structure" +weight = 30 ++++ + +After running `zola init`, you should see the following structure in your directory: + + +```bash +. +├── config.toml +├── content +├── sass +├── static +├── templates +└── themes + +5 directories, 1 file +``` + +Here's a high-level overview of each of these directories and `config.toml`. + +## `config.toml` +A mandatory Zola configuration file in TOML format. +This file is explained in detail in the [configuration documentation](@/getting-started/configuration.md). + +## `content` +Contains all your markup content (mostly `.md` files). +Each child directory of the `content` directory represents a [section](@/content/section.md) +that contains [pages](@/content/page.md) (your `.md` files). + +To learn more, read the [content overview page](@/content/overview.md). + +## `sass` +Contains the [Sass](http://sass-lang.com) files to be compiled. Non-Sass files will be ignored. +The directory structure of the `sass` folder will be preserved when copying over the compiled files; for example, a file at +`sass/something/site.scss` will be compiled to `public/something/site.css`. + +## `static` +Contains any kind of file. All the files/directories in the `static` directory will be copied as-is to the output directory. +If your static files are large, you can configure Zola to [hard link](https://en.wikipedia.org/wiki/Hard_link) them +instead of copying them by setting `hard_link_static = true` in the config file. + +## `templates` +Contains all the [Tera](https://tera.netlify.com) templates that will be used to render your site. +Have a look at the [templates documentation](@/templates/_index.md) to learn more about default templates +and available variables. + +## `themes` +Contains themes that can be used for your site. If you are not planning to use themes, leave this directory empty. +If you want to learn about themes, see the [themes documentation](@/themes/_index.md). diff --git a/content/getting-started/installation.md b/content/getting-started/installation.md new file mode 100644 index 0000000..3fd9aac --- /dev/null +++ b/content/getting-started/installation.md @@ -0,0 +1,107 @@ ++++ +title = "Installation" +weight = 10 ++++ + +Zola provides pre-built binaries for MacOS, Linux and Windows on the +[GitHub release page](https://github.com/getzola/zola/releases). + +### macOS + +Zola is available on [Brew](https://brew.sh): + +```bash +$ brew install zola +``` + +### Arch Linux + +Zola is available in the official Arch Linux repositories. + +```bash +$ pacman -S zola +``` + +### Fedora + +Zola has been available in the official repositories since Fedora 29. + +```sh +$ sudo dnf install zola +``` + +### Void Linux +Zola is available in the official Void Linux repositories. + +```sh +$ sudo xbps-install zola +``` + +### FreeBSD + +Zola is available in the official package repository. + +```sh +$ pkg install zola +``` + +### OpenBSD +Zola is available in the official package repository. + +```sh +$ doas pkg_add zola +``` + +### Snapcraft + +Zola is available on snapcraft: + +```bash +$ snap install --edge zola +``` + +## Windows + +Zola is available on [Scoop](http://scoop.sh): + +```bash +$ scoop install zola +``` + +and [Chocolatey](https://chocolatey.org/): + +```bash +$ choco install zola +``` + +Zola does not work in PowerShell ISE. + +## From source +To build Zola from source, you will need to have Git, [Rust (at least 1.43) and Cargo](https://www.rust-lang.org/) +installed. You will also need to meet additional dependencies to compile [libsass](https://github.com/sass/libsass): + +- OSX, Linux and other Unix-like operating systems: `make` (`gmake` on BSDs), `g++`, `libssl-dev` + - NixOS: Create a `shell.nix` file in the root of the cloned project with the following contents: + ```nix + with import {}; + + pkgs.mkShell { + buildInputs = [ + libsass + openssl + pkgconfig + ]; + } + ``` + - Then, invoke `nix-shell`. This opens a shell with the above dependencies. Then, run `cargo build --release` to build the project. +- Windows (a bit trickier): updated `MSVC` and overall updated VS installation + +From a terminal, you can now run the following command: + +```bash +$ cargo build --release +``` + +The binary will be available in the `target/release` directory. You can move it in your `$PATH` to have the +`zola` command available globally or in a directory if you want for example to have the binary in the +same repository as the site. diff --git a/content/getting-started/overview.md b/content/getting-started/overview.md new file mode 100644 index 0000000..06e41c6 --- /dev/null +++ b/content/getting-started/overview.md @@ -0,0 +1,208 @@ ++++ +title = "Overview" +weight = 5 ++++ + +## Zola at a Glance + +Zola is a static site generator (SSG), similar to [Hugo](https://gohugo.io/), [Pelican](https://blog.getpelican.com/), and [Jekyll](https://jekyllrb.com/) (for a comprehensive list of SSGs, please see the [StaticGen](https://www.staticgen.com/) site). It is written in [Rust](https://www.rust-lang.org/) and uses the [Tera](https://tera.netlify.com/) template engine, which is similar to [Jinja2](https://jinja.palletsprojects.com/en/2.10.x/), [Django templates](https://docs.djangoproject.com/en/2.2/topics/templates/), [Liquid](https://shopify.github.io/liquid/), and [Twig](https://twig.symfony.com/). Content is written in [CommonMark](https://commonmark.org/), a strongly defined, highly compatible specification of [Markdown](https://www.markdownguide.org/). + +SSGs use dynamic templates to transform content into static HTML pages. Static sites are thus very fast and require no databases, making them easy to host. A comparison between static and dynamic sites, such as WordPress, Drupal, and Django, can be found [here](https://dev.to/ashenmaster/static-vs-dynamic-sites-61f). + +To get a taste of Zola, please see the quick overview below. + +## First Steps with Zola + +Unlike some SSGs, Zola makes no assumptions regarding the structure of your site. In this overview, we'll be making a simple blog site. + +### Initialize Site + +> This overview is based on Zola 0.9. + +Please see the detailed [installation instructions for your platform](@/getting-started/installation.md). With Zola installed, let's initialize our site: + +```bash +$ zola init myblog +``` + +You will be asked a few questions. + +``` +> What is the URL of your site? (https://example.com): +> Do you want to enable Sass compilation? [Y/n]: +> Do you want to enable syntax highlighting? [y/N]: +> Do you want to build a search index of the content? [y/N]: +``` + + For our blog, let's accept the default values (i.e., press Enter for each question). We now have a `myblog` directory with the following structure: + +```bash +├── config.toml +├── content +├── sass +├── static +├── templates +└── themes +``` + +Let's start the Zola development server with: + +```bash +$ zola serve +Building site... +-> Creating 0 pages (0 orphan), 0 sections, and processing 0 images +``` + +> This command must be run in the base Zola directory, which contains `config.toml`. + +If you point your web browser to , you should see a "Welcome to Zola" message. + +### Home Page + +Let's make a home page. To do this, let's first create a `base.html` file inside the `templates` directory. This step will make more sense as we move through this overview. We'll be using the CSS framework [Bulma](https://bulma.io/). + +```html + + + + + + MyBlog + + + + +
+
+ {% block content %} {% endblock %} +
+
+ + + +``` + +Now, let's create an `index.html` file inside the `templates` directory. + +```html +{% extends "base.html" %} + +{% block content %} +

+ This is my blog made with Zola. +

+{% endblock content %} +``` + +This tells Zola that `index.html` extends our `base.html` file and replaces the block called "content" with the text between the `{% block content %}` and `{% endblock content %}` tags. + +### Content Directory + +Now let's add some content. We'll start by making a `blog` subdirectory in the `content` directory and creating an `_index.md` file inside it. This file tells Zola that `blog` is a [section](@/content/section.md), which is how content is categorized in Zola. + +```bash +├── content +│ └── blog +│ └── _index.md +``` + +In the `_index.md` file, we'll set the following variables in [TOML](https://github.com/toml-lang/toml) format: + +```md ++++ +title = "List of blog posts" +sort_by = "date" +template = "blog.html" +page_template = "blog-page.html" ++++ +``` + +> Note that although no variables are mandatory, the opening and closing `+++` are required. + +* *sort_by = "date"* tells Zola to use the date to order our section pages (more on pages below). +* *template = "blog.html"* tells Zola to use `blog.html` in the `templates` directory as the template for listing the Markdown files in this section. +* *page_template = "blog-page.html"* tells Zola to use `blog-page.html` in the `templates` directory as the template for individual Markdown files. + +For a full list of section variables, please see the [section](@/content/section.md) documentation. We will use *title = "List of blog posts"* in a template (see below). + +### Templates + +Let's now create some more templates. In the `templates` directory, create a `blog.html` file with the following contents: + +```html +{% extends "base.html" %} + +{% block content %} +

+ {{ section.title }} +

+ +{% endblock content %} +``` + +As done by `index.html`, `blog.html` extends `base.html`, but this time we want to list the blog posts. The *title* we set in the `_index.md` file above is available to us as `{{ section.title }}`. In the list below the title, we loop through all the pages in our section (`blog` directory) and output the page title and URL using `{{ page.title }}` and `{{ page.permalink | safe }}`, respectively. We use the `| safe` filter because the permalink doesn't need to be HTML escaped (escaping would cause `/` to render as `/`). + +If you go to , you will see the section page for `blog`. The list is empty because we don't have any blog posts. Let's fix that now. + +### Markdown Content + +In the `blog` directory, create a file called `first.md` with the following contents: + +```md ++++ +title = "My first post" +date = 2019-11-27 ++++ + +This is my first blog post. +``` + +The *title* and *date* will be available to us in the `blog-page.html` template as `{{ page.title }}` and `{{ page.date }}`, respectively. All text below the closing `+++` will be available to us as `{{ page.content }}`. + +We now need to make the `blog-page.html` template. In the `templates` directory, create this file with the contents: + +```html +{% extends "base.html" %} + +{% block content %} +

+ {{ page.title }} +

+

{{ page.date }}

+{{ page.content | safe }} +{% endblock content %} +``` + +> Note the `| safe` filter for `{{ page.content }}`. + +This should start to look familiar. If you now go back to our blog list page at , you should see our lonely post. Let's add another. In the `content/blog` directory, let's create the file `second.md` with the contents: + +```md ++++ +title = "My second post" +date = 2019-11-28 ++++ + +This is my second blog post. +``` + +Back at , our second post shows up on top of the list because it's newer than the first post and we had set *sort_by = "date"* in our `_index.md` file. As a final step, let's modify our home page to link to our blog posts. + +The `index.html` file inside the `templates` directory should be: + +```html +{% extends "base.html" %} + +{% block content %} +

+ This is my blog made with Zola. +

+

Click here to see my posts.

+{% endblock content %} +``` + +This has been a quick overview of Zola. You can now dive into the rest of the documentation. diff --git a/content/templates/404.md b/content/templates/404.md new file mode 100644 index 0000000..eb0a558 --- /dev/null +++ b/content/templates/404.md @@ -0,0 +1,7 @@ ++++ +title = "404 error page" +weight = 80 ++++ + +Zola will look for a `404.html` file in the `templates` directory or +use the built-in one. The default template is very basic and gets `config` in its context. diff --git a/content/templates/_index.md b/content/templates/_index.md new file mode 100644 index 0000000..3c56b87 --- /dev/null +++ b/content/templates/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Templates" +weight = 3 +sort_by = "weight" ++++ diff --git a/content/templates/archive.md b/content/templates/archive.md new file mode 100644 index 0000000..467d12c --- /dev/null +++ b/content/templates/archive.md @@ -0,0 +1,23 @@ ++++ +title = "Archive" +weight = 90 ++++ + +Zola doesn't have a built-in way to display an archive page (a page showing +all post titles ordered by year). However, this can be accomplished directly in the templates: + +```jinja2 +{% for year, posts in section.pages | group_by(attribute="year") %} +

{{ year }}

+ + +{% endfor %} +``` + +This snippet assumes that posts are sorted by date and that you want to display the archive +in descending order. If you want to show articles in ascending order, add a `reverse` filter +after `group_by`. diff --git a/content/templates/feeds/index.md b/content/templates/feeds/index.md new file mode 100644 index 0000000..9ac72e2 --- /dev/null +++ b/content/templates/feeds/index.md @@ -0,0 +1,64 @@ ++++ +title = "Feeds" +weight = 50 +aliases = ["/documentation/templates/rss/"] ++++ + +If the site `config.toml` file sets `generate_feed = true`, then Zola will +generate a feed file for the site, named according to the `feed_filename` +setting in `config.toml`, which defaults to `atom.xml`. Given the feed filename +`atom.xml`, the generated file will live at `base_url/atom.xml`, based upon the +`atom.xml` file in the `templates` directory, or the built-in Atom template. + +`feed_filename` can be set to any value, but built-in templates are provided +for `atom.xml` (in the preferred Atom 1.0 format), and `rss.xml` (in the RSS +2.0 format). If you choose a different filename (e.g. `feed.xml`), you will +need to provide a template yourself. + +**Only pages with a date will be available.** + +The feed template gets five variables: + +- `config`: the site config +- `feed_url`: the full url to that specific feed +- `last_updated`: the most recent `updated` or `date` field of any post +- `pages`: see [page variables](@/templates/pages-sections.md#page-variables) + for a detailed description of what this contains +- `lang`: the language code that applies to all of the pages in the feed, + if the site is multilingual, or `config.default_language` if it is not + +Feeds for taxonomy terms get two more variables, using types from the +[taxonomies templates](@/templates/taxonomies.md): + +- `taxonomy`: of type `TaxonomyConfig` +- `term`: of type `TaxonomyTerm`, but without `term.pages` (use `pages` instead) + +You can also enable separate feeds for each section by setting the +`generate_feed` variable to true in the respective section's front matter. +Section feeds will use the same template as indicated in the `config.toml` file. +Section feeds, in addition to the five feed template variables, get the +`section` variable from the [section template](@/templates/pages-sections.md). + +Enable feed autodiscovery allows feed readers and browsers to notify user about a RSS or Atom feed available on your web site. So it is easier for user to subscribe. +As an example this is how it looks like using [Firefox](https://en.wikipedia.org/wiki/Mozilla_Firefox) [Livemarks](https://addons.mozilla.org/en-US/firefox/addon/livemarks/?src=search) addon. + +![RSS feed autodiscovery example.](rss_feed.png) + +You can enable posts autodiscovery modifying your blog `base.html` template adding the following code in between the `` tags. +```html +{% block rss %} + +{% endblock %} +``` +You can as well use an Atom feed using `type="application/atom+xml"` and `path="atom.xml"`. + +All pages on your site will refer to your post feed. + +In order to enable the tag feeds as well, you can overload the `block rss` using the following code in your `tags/single.html` template. +```html +{% block rss %} + {% set rss_path = "tags/" ~ term.name ~ "/rss.xml" %} + +{% endblock rss %} +``` +Each tag page will refer to it's dedicated feed. diff --git a/content/templates/feeds/rss_feed.png b/content/templates/feeds/rss_feed.png new file mode 100644 index 0000000..81abb70 Binary files /dev/null and b/content/templates/feeds/rss_feed.png differ diff --git a/content/templates/overview.md b/content/templates/overview.md new file mode 100644 index 0000000..7f19005 --- /dev/null +++ b/content/templates/overview.md @@ -0,0 +1,343 @@ ++++ +title = "Overview" +weight = 10 ++++ + +Zola uses the [Tera](https://tera.netlify.com) template engine, which is very similar +to Jinja2, Liquid and Twig. + +As this documentation will only talk about how templates work in Zola, please read +the [Tera template documentation](https://tera.netlify.com/docs#templates) if you want +to learn more about it first. + +All templates live in the `templates` directory. If you are not sure what variables are available in a template, +you can place `{{ __tera_context }}` in the template to print the whole context. + +A few variables are available on all templates except feeds and the sitemap: + +- `config`: the [configuration](@/getting-started/configuration.md) without any modifications +- `current_path`: the path (full URL without `base_url`) of the current page, always starting with a `/` +- `current_url`: the full URL for the current page +- `lang`: the language for the current page + +Config variables can be accessed like `config.variable`, in HTML for example with `{{ config.base_url }}`. +The 404 template does not get `current_path` and `current_url` (this information cannot be determined). + +## Standard templates +By default, Zola will look for three templates: `index.html`, which is applied +to the site homepage; `section.html`, which is applied to all sections (any HTML +page generated by creating a directory within your `content` directory); and +`page.html`, which is applied to all pages (any HTML page generated by creating an +`.md` file within your `content` directory). + +The homepage is always a section (regardless of whether it contains other pages). +Thus, the `index.html` and `section.html` templates both have access to the +section variables. The `page.html` template has access to the page variables. +The page and section variables are described in more detail in the next section. + +## Built-in templates +Zola comes with four built-in templates: `atom.xml` and `rss.xml` (described in +[Feeds](@/templates/feeds/index.md)), `sitemap.xml` (described in [Sitemap](@/templates/sitemap.md)), +and `robots.txt` (described in [Robots.txt](@/templates/robots.md)). +Additionally, themes can add their own templates, which will be applied if not +overridden. You can override built-in or theme templates by creating a template with +the same name in the correct path. For example, you can override the Atom template by +creating a `templates/atom.xml` file. + +## Custom templates +In addition to the standard `index.html`, `section.html` and `page.html` templates, +you may also create custom templates by creating an `.html` file in the `templates` +directory. These custom templates will not be used by default. Instead, a custom template will _only_ be used if you apply it by setting the `template` front-matter variable to the path for that template (or if you `include` it in another template that is applied). For example, if you created a custom template for your site's About page called `about.html`, you could apply it to your `about.md` page by including the following front matter in your `about.md` page: + +```md ++++ +title = "About Us" +template = "about.html" ++++ +``` + +Custom templates are not required to live at the root of your `templates` directory. +For example, `product_pages/with_pictures.html` is a valid template. + +## Built-in filters +Zola adds a few filters in addition to [those](https://tera.netlify.com/docs/#filters) already present +in Tera. + +### markdown +Converts the given variable to HTML using Markdown. This doesn't apply any of the +features that Zola adds to Markdown; for example, internal links and shortcodes won't work. + +By default, the filter will wrap all text in a paragraph. To disable this behaviour, you can +pass `true` to the inline argument: + +```jinja2 +{{ some_text | markdown(inline=true) }} +``` + +You do not need to use this filter with `page.content` or `section.content`, the content is already rendered. + +### base64_encode +Encode the variable to base64. + +### base64_decode +Decode the variable from base64. + + +## Built-in global functions + +Zola adds a few global functions to [those in Tera](https://tera.netlify.com/docs#built-in-functions) +to make it easier to develop complex sites. + + +### `get_page` +Takes a path to an `.md` file and returns the associated page. + +```jinja2 +{% set page = get_page(path="blog/page2.md") %} +``` + +### `get_section` +Takes a path to an `_index.md` file and returns the associated section. + +```jinja2 +{% set section = get_section(path="blog/_index.md") %} +``` + +If you only need the metadata of the section, you can pass `metadata_only=true` to the function: + +```jinja2 +{% set section = get_section(path="blog/_index.md", metadata_only=true) %} +``` + +### `get_url` +Gets the permalink for the given path. +If the path starts with `@/`, it will be treated as an internal +link like the ones used in Markdown, starting from the root `content` directory. + +```jinja2 +{% set url = get_url(path="@/blog/_index.md") %} +``` + +It accepts an optional parameter `lang` in order to compute a *language-aware URL* in multilingual websites. Assuming `config.base_url` is `"http://example.com"`, the following snippet will: + +- return `"http://example.com/blog/"` if `config.default_language` is `"en"` +- return `"http://example.com/en/blog/"` if `config.default_language` is **not** `"en"` and `"en"` appears in `config.languages` +- fail otherwise, with the error message `"'en' is not an authorized language (check config.languages)."` + +```jinja2 +{% set url = get_url(path="@/blog/_index.md", lang="en") %} +``` + +This can also be used to get the permalinks for static assets, for example if +we want to link to the file that is located at `static/css/app.css`: + +```jinja2 +{{/* get_url(path="css/app.css") */}} +``` + +By default, assets will not have a trailing slash. You can force one by passing `trailing_slash=true` to the `get_url` function. +An example is: + +```jinja2 +{{/* get_url(path="css/app.css", trailing_slash=true) */}} +``` + +In the case of non-internal links, you can also add a cachebust of the format `?h=` at the end of a URL +by passing `cachebust=true` to the `get_url` function. + + +### `get_file_hash` + +Gets the hash digest for a static file. Supported hashes are SHA-256, SHA-384 (default) and SHA-512. Requires `path`. The `sha_type` key is optional and must be one of 256, 384 or 512. + +```jinja2 +{{/* get_file_hash(path="js/app.js", sha_type=256) */}} +``` + +This can be used to implement subresource integrity. Do note that subresource integrity is typically used when using external scripts, which `get_file_hash` does not support. + +```jinja2 + +``` + +Whenever hashing files, whether using `get_file_hash` or `get_url(..., cachebust=true)`, the file is searched for in three places: `static/`, `content/` and the output path (so e.g. compiled SASS can be hashed, too.) + + +### `get_image_metadata` +Gets metadata for an image. This supports common formats like JPEG, PNG, as well as SVG. +Currently, the only supported keys are `width` and `height`. + +```jinja2 + {% set meta = get_image_metadata(path="...") %} + Our image is {{ meta.width }}x{{ meta.height }} +``` + +### `get_taxonomy_url` +Gets the permalink for the taxonomy item found. + +```jinja2 +{% set url = get_taxonomy_url(kind="categories", name=page.taxonomies.category, lang=page.lang) %} +``` + +`name` will almost always come from a variable but in case you want to do it manually, +the value should be the same as the one in the front matter, not the slugified version. + +`lang` (optional) default to `config.default_language` in config.toml + +### `get_taxonomy` +Gets the whole taxonomy of a specific kind. + +```jinja2 +{% set categories = get_taxonomy(kind="categories") %} +``` + +The type of the output is: + +```ts +kind: TaxonomyConfig; +items: Array; +``` + +See the [Taxonomies documentation](@/templates/taxonomies.md) for a full documentation of those types. + +### `load_data` +Loads data from a file or URL. Supported file types include *toml*, *json*, *csv* and *bibtex*. +Any other file type will be loaded as plain text. + +The `path` argument specifies the path to the data file relative to your base directory, where your `config.toml` is. +As a security precaution, if this file is outside the main site directory, your site will fail to build. + +```jinja2 +{% set data = load_data(path="content/blog/story/data.toml") %} +``` + +The optional `format` argument allows you to specify and override which data type is contained +within the file specified in the `path` argument. Valid entries are `toml`, `json`, `csv`, `bibtex` +or `plain`. If the `format` argument isn't specified, then the path extension is used. + +```jinja2 +{% set data = load_data(path="content/blog/story/data.txt", format="json") %} +``` + +Use the `plain` format for when your file has a toml/json/csv extension but you want to load it as plain text. + +For *toml* and *json*, the data is loaded into a structure matching the original data file; +however, for *csv* there is no native notion of such a structure. Instead, the data is separated +into a data structure containing *headers* and *records*. See the example below to see +how this works. + +In the template: +```jinja2 +{% set data = load_data(path="content/blog/story/data.csv") %} +``` + +In the *content/blog/story/data.csv* file: +```csv +Number, Title +1,Gutenberg +2,Printing +``` + +The equivalent json value of the parsed data would be stored in the `data` variable in the +template: +```json +{ + "headers": ["Number", "Title"], + "records": [ + ["1", "Gutenberg"], + ["2", "Printing"] + ], +} +``` + +The `bibtex` format loads data into a structure matching the format used by the +[nom-bibtex crate](https://crates.io/crates/nom-bibtex). The following is an example of data +in bibtex format: + +``` +@preamble{"A bibtex preamble" # " this is."} + +@Comment{ + Here is a comment. +} + +Another comment! + +@string(name = "Vincent Prouillet") +@string(github = "https://github.com/getzola/zola") + +@misc {my_citation_key, + author= name, + title = "Zola", + note = "github: " # github +} } +``` + +The following is the json-equivalent format of the produced bibtex data structure: +```json +{ + "preambles": ["A bibtex preamble this is."], + "comments": ["Here is a comment.", "Another comment!"], + "variables": { + "name": "Vincent Prouillet", + "github": "https://github.com/getzola/zola" + }, + "bibliographies": [ + { + "entry_type": "misc", + "citation_key": "my_citation_key", + "tags": { + "author": "Vincent Prouillet", + "title": "Zola", + "note": "github: https://github.com/getzola/zola" + } + } + ] +} +``` + +Finally, the bibtex data can be accessed from the template as follows: +```jinja2 +{% set tags = data.bibliographies[0].tags %} +This was generated using {{ tags.title }}, authored by {{ tags.author }}. +``` + +#### Remote content + +Instead of using a file, you can load data from a remote URL. This can be done by specifying a `url` parameter +to `load_data` rather than `path`. + +```jinja2 +{% set response = load_data(url="https://api.github.com/repos/getzola/zola") %} +{{ response }} +``` + +By default, the response body will be returned with no parsing. This can be changed by using the `format` argument +as below. + + +```jinja2 +{% set response = load_data(url="https://api.github.com/repos/getzola/zola", format="json") %} +{{ response }} +``` + +#### Data caching + +Data file loading and remote requests are cached in memory during the build, so multiple requests aren't made +to the same endpoint. +URLs are cached based on the URL, and data files are cached based on the file modified time. +The format is also taken into account when caching, so a request will be sent twice if it's loaded with two +different formats. + +### `trans` +Gets the translation of the given `key`, for the `default_language` or the `lang`uage given + +```jinja2 +{{/* trans(key="title") */}} +{{/* trans(key="title", lang="fr") */}} +``` + +### `resize_image` +Resizes an image file. +Please refer to Content / Image Processing for complete documentation. diff --git a/content/templates/pages-sections.md b/content/templates/pages-sections.md new file mode 100644 index 0000000..ec550ed --- /dev/null +++ b/content/templates/pages-sections.md @@ -0,0 +1,145 @@ ++++ +title = "Sections and Pages" +weight = 20 ++++ + +Templates for pages and sections are very similar. + +## Page variables +Zola will try to load the `templates/page.html` template, the `page.html` template of the theme if one is used +or render the built-in template (a blank page). + +Whichever template you decide to render, you will get a `page` variable in your template +with the following fields: + + +```ts +// The HTML output of the Markdown content +content: String; +title: String?; +description: String?; +date: String?; +// `updated` will be the same as `date` if `date` is specified but `updated` is not in front-matter +updated: String?; +slug: String; +path: String; +draft: Bool; +// the path, split on '/' +components: Array; +permalink: String; +summary: String?; +taxonomies: HashMap>; +extra: HashMap; +toc: Array
, +// Naive word count, will not work for languages without whitespace +word_count: Number; +// Based on https://help.medium.com/hc/en-us/articles/214991667-Read-time +reading_time: Number; +// `earlier` and `later` are only populated if the section variable `sort_by` is set to `date` +// and only set when rendering the page itself +earlier: Page?; +later: Page?; +// `heavier` and `lighter` are only populated if the section variable `sort_by` is set to `weight` +// and only set when rendering the page itself +heavier: Page?; +lighter: Page?; +// Year/month/day is only set if the page has a date and month/day are 1-indexed +year: Number?; +month: Number?; +day: Number?; +// Paths of colocated assets, relative to the content directory +assets: Array; +// The relative paths of the parent sections until the index one, for use with the `get_section` Tera function +// The first item is the index section and the last one is the parent section +// This is filled after rendering a page content so it will be empty in shortcodes +ancestors: Array; +// The relative path from the `content` directory to the markdown file +relative_path: String; +// The language for the page if there is one. Default to the config `default_language` +lang: String; +// Information about all the available languages for that content +translations: Array; +``` + +## Section variables +By default, Zola will try to load `templates/index.html` for `content/_index.md` +and `templates/section.html` for other `_index.md` files. If there isn't +one, it will render the built-in template (a blank page). + +Whichever template you decide to render, you will get a `section` variable in your template +with the following fields: + + +```ts +// The HTML output of the Markdown content +content: String; +title: String?; +description: String?; +path: String; +// the path, split on '/' +components: Array; +permalink: String; +extra: HashMap; +// Pages directly in this section. By default, the pages are not sorted. Please set the "sorted_by" +// variable in the _index.md file of the corresponding section to "date" or "weight" for sorting by +// date and weight, respectively. +pages: Array; +// Direct subsections to this section, sorted by subsections weight +// This only contains the path to use in the `get_section` Tera function to get +// the actual section object if you need it +subsections: Array; +toc: Array
, +// Unicode word count +word_count: Number; +// Based on https://help.medium.com/hc/en-us/articles/214991667-Read-time +reading_time: Number; +// Paths of colocated assets, relative to the content directory +assets: Array; +// The relative paths of the parent sections until the index one, for use with the `get_section` Tera function +// The first item is the index section and the last one is the parent section +// This is filled after rendering a page content so it will be empty in shortcodes +ancestors: Array; +// The relative path from the `content` directory to the markdown file +relative_path: String; +// The language for the section if there is one. Default to the config `default_language` +lang: String; +// Information about all the available languages for that content +translations: Array; +``` + +## Table of contents + +Both page and section templates have a `toc` variable that corresponds to an array of `Header`. +A `Header` has the following fields: + +```ts +// The hX level +level: 1 | 2 | 3 | 4 | 5 | 6; +// The generated slug id +id: String; +// The text of the header +title: String; +// A link pointing directly to the header, using the inserted anchor +permalink: String; +// All lower level headers below this header +children: Array
; +``` + +## Translated content + +Both pages and sections have a `translations` field that corresponds to an array of `TranslatedContent`. If your +site is not using multiple languages, this will always be an empty array. +`TranslatedContent` has the following fields: + +```ts +// The language code for that content, empty if it is the default language +lang: String?; +// The title of that content if there is one +title: String?; +// A permalink to that content +permalink: String; +// The path to the markdown file; useful for retrieving the full page through +// the `get_page` function. +path: String; +``` + diff --git a/content/templates/pagination.md b/content/templates/pagination.md new file mode 100644 index 0000000..846a2cc --- /dev/null +++ b/content/templates/pagination.md @@ -0,0 +1,51 @@ ++++ +title = "Pagination" +weight = 30 ++++ + +Two things can get paginated: a section and a taxonomy term. + +Both kinds get a `paginator` variable of the `Pager` type, on top of the common variables mentioned in the +[overview page](@/templates/overview.md): + +```ts +// How many items per pager +paginate_by: Number; +// The base URL for the pagination: section permalink + pagination path +// You can concatenate an integer with that to get a link to a given pagination pager. +base_url: String; +// How many pagers in total +number_pagers: Number; +// Permalink to the first pager +first: String; +// Permalink to the last pager +last: String; +// Permalink to the previous pager, if there is one +previous: String?; +// Permalink to the next pager, if there is one +next: String?; +// All pages for the current pager +pages: Array; +// Which pager are we on +current_index: Number; +// Total number of pages accross all the pagers +total_pages: Number; +``` + +A pager is a page of the pagination; if you have 100 pages and paginate_by is set to 10, you will have 10 pagers each +containing 10 pages. + +## Section + +A paginated section gets the same `section` variable as a normal +[section page](@/templates/pages-sections.md#section-variables) +minus its pages. The pages are instead in `paginator.pages`. + +## Taxonomy term + +A paginated taxonomy gets two variables aside from the `paginator` variable: + +- a `taxonomy` variable of type `TaxonomyConfig` +- a `term` variable of type `TaxonomyTerm`. + +See the [taxonomies page](@/templates/taxonomies.md) for a detailed version of the types. diff --git a/content/templates/robots.md b/content/templates/robots.md new file mode 100644 index 0000000..40a1089 --- /dev/null +++ b/content/templates/robots.md @@ -0,0 +1,16 @@ ++++ +title = "Robots.txt" +weight = 70 ++++ + +Zola will look for a `robots.txt` file in the `templates` directory or +use the built-in one. + +Robots.txt is the simplest of all templates: it only gets `config` +and the default is what most sites want: + +```jinja2 +User-agent: * +Allow: / +Sitemap: {{/* get_url(path="sitemap.xml") */}} +``` diff --git a/content/templates/sitemap.md b/content/templates/sitemap.md new file mode 100644 index 0000000..3c21351 --- /dev/null +++ b/content/templates/sitemap.md @@ -0,0 +1,34 @@ ++++ +title = "Sitemap" +weight = 60 ++++ + +Zola will look for a `sitemap.xml` file in the `templates` directory or +use the built-in one. + +If your site has more than 30 000 pages, it will automatically split +the links into multiple sitemaps, as recommended by [Google](https://support.google.com/webmasters/answer/183668?hl=en): + +> All formats limit a single sitemap to 50MB (uncompressed) and 50,000 URLs. +> If you have a larger file or more URLs, you will have to break your list into multiple sitemaps. +> You can optionally create a sitemap index file (a file that points to a list of sitemaps) and submit +> that single index file to Google. + +In such a case, Zola will use a template called `split_sitemap_index.xml` to render the index sitemap. + + +The `sitemap.xml` template gets a single variable: + +- `entries`: all pages of the site, as a list of `SitemapEntry` + +A `SitemapEntry` has the following fields: + +```ts +permalink: String; +updated: String?; +extra: Hashmap?; +``` + +The `split_sitemap_index.xml` also gets a single variable: + +- `sitemaps`: a list of permalinks to the sitemaps diff --git a/content/templates/taxonomies.md b/content/templates/taxonomies.md new file mode 100644 index 0000000..1ca3286 --- /dev/null +++ b/content/templates/taxonomies.md @@ -0,0 +1,68 @@ ++++ +title = "Taxonomies" +weight = 40 ++++ + +Zola will look up the following files in the `templates` directory: + +- `$TAXONOMY_NAME/single.html` +- `$TAXONOMY_NAME/list.html` + +First, `TaxonomyTerm` has the following fields: + +```ts +name: String; +slug: String; +permalink: String; +pages: Array; +``` + +and `TaxonomyConfig` has the following fields: + +```ts +name: String, +paginate_by: Number?; +paginate_path: String?; +feed: Bool; +lang: String; +``` + + +### Taxonomy list (`list.html`) + +This template is never paginated and therefore gets the following variables in all cases. + +```ts +// The site config +config: Config; +// The data of the taxonomy, from the config +taxonomy: TaxonomyConfig; +// The current full permalink for that page +current_url: String; +// The current path for that page +current_path: String; +// All terms for that taxonomy +terms: Array; +// The lang of the current page +lang: String; +``` + + +### Single term (`single.html`) +```ts +// The site config +config: Config; +// The data of the taxonomy, from the config +taxonomy: TaxonomyConfig; +// The current full permalink for that page +current_url: String; +// The current path for that page +current_path: String; +// The current term being rendered +term: TaxonomyTerm; +// The lang of the current page +lang: String; +``` + +A paginated taxonomy term will also get a `paginator` variable; see the +[pagination page](@/templates/pagination.md) for more details. diff --git a/content/testing/01-why.md b/content/testing/01-why.md new file mode 100644 index 0000000..fb565ea --- /dev/null +++ b/content/testing/01-why.md @@ -0,0 +1,6 @@ ++++ +title = "Testing" +weight = 10 ++++ + +Another start to another day. diff --git a/content/testing/_index.md b/content/testing/_index.md new file mode 100644 index 0000000..cef5555 --- /dev/null +++ b/content/testing/_index.md @@ -0,0 +1,6 @@ ++++ +title = "Testing" +weight = 2 +sort_by = "weight" +insert_anchor_links = "right" ++++ diff --git a/content/themes/_index.md b/content/themes/_index.md new file mode 100644 index 0000000..938a8e2 --- /dev/null +++ b/content/themes/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Themes" +weight = 4 +sort_by = "weight" ++++ diff --git a/content/themes/creating-a-theme.md b/content/themes/creating-a-theme.md new file mode 100644 index 0000000..b01577c --- /dev/null +++ b/content/themes/creating-a-theme.md @@ -0,0 +1,72 @@ ++++ +title = "Creating a theme" +weight = 30 ++++ + +Creating a theme is exactly like creating a normal site with Zola, except you +will want to use many [Tera blocks](https://tera.netlify.com/docs#inheritance) to +allow users to easily modify it. + +## Getting started +As mentioned, a theme is just like any site; start by running `zola init MY_THEME_NAME`. + +The only thing needed to turn that site into a theme is to add a `theme.toml` configuration file with the +following fields: + +```toml +name = "my theme name" +description = "A classic blog theme" +license = "MIT" +homepage = "https://github.com/getzola/hyde" +# The minimum version of Zola required +min_version = "0.4.0" +# An optional live demo URL +demo = "" + +# Any variable there can be overriden in the end user `config.toml` +# You don't need to prefix variables by the theme name but as this will +# be merged with user data, some kind of prefix or nesting is preferable +# Use snake_casing to be consistent with the rest of Zola +[extra] + +# The theme author info: you! +[author] +name = "Vincent Prouillet" +homepage = "https://vincent.is" + +# If this is porting a theme from another static site engine, provide +# the info of the original author here +[original] +author = "mdo" +homepage = "http://markdotto.com/" +repo = "https://www.github.com/mdo/hyde" +``` + +A simple theme you can use as an example is [Hyde](https://github.com/Keats/hyde). + +## Working on a theme +As a theme is just a site, you can simply use `zola serve` and make changes to your +theme, with live reload working as expected. + +Make sure to commit every directory (including `content`) in order for other people +to be able to build the theme from your repository. + +## Submitting a theme to the gallery + +If you want your theme to be featured in the [themes](@/themes/_index.md) section +of this site, the theme will require two more things: + +- `screenshot.png`: a screenshot of the theme in action with a max size of around 2000x1000 +- `README.md`: a thorough README explaining how to use the theme and any other information +of importance + +The first step is to make sure that the theme meets the following three requirements: + +- have a `screenshot.png` of the theme in action with a max size of around 2000x1000 +- have a thorough `README.md` explaining how to use the theme and any other information +of importance +- be of reasonably high quality + +When your theme is ready, you can submit it to the [themes repository](https://github.com/getzola/themes) +by following the process in the README. + diff --git a/content/themes/extending-a-theme.md b/content/themes/extending-a-theme.md new file mode 100644 index 0000000..d403427 --- /dev/null +++ b/content/themes/extending-a-theme.md @@ -0,0 +1,21 @@ ++++ +title = "Extending a theme" +weight = 30 ++++ + +When your site uses a theme, you can replace parts of it in your site's templates folder. For any given theme template, you can either override a single block in it, or replace the whole template. If a site template and a theme template collide, the site template will be given priority. Whether a theme template collides or not, theme templates remain accessible from any template within `theme_name/templates/`. + +## Replacing a template + +When a site template and a theme template have the same path, for example `templates/page.html` and `themes/theme_name/templates/page.html`, the site template is the one that will be used. This is how you can replace a whole template for a theme. + +## Overriding a block + +If you don't want to replace a whole template, but override parts of it, you can [extend the template](https://tera.netlify.app/docs/#inheritance) and redefine some specific blocks. For example, if you want to override the `title` block in your theme's page.html, you can create a page.html file in your site templates with the following content: + +``` +{% extends "theme_name/templates/page.html" %} +{% block title %}{{ page.title }}{% endblock %} +``` + +If you extend `page.html` and not `theme_name/templates/page.html` specifically, it will extend the site's page template if it exists, and the theme's page template otherwise. This makes it possible to override your theme's base template(s) from your site templates, as long as the theme templates do not hardcode the theme name in template paths. For instance, children templates in the theme should use `{% extends 'index.html' %}`, not `{% extends 'theme_name/templates/index.html' %}`. diff --git a/content/themes/installing-and-using-themes.md b/content/themes/installing-and-using-themes.md new file mode 100644 index 0000000..5afbb45 --- /dev/null +++ b/content/themes/installing-and-using-themes.md @@ -0,0 +1,65 @@ ++++ +title = "Installing & using themes" +weight = 20 ++++ + + +## Installing a theme + +The easiest way to install a theme is to clone its repository in the `themes` +directory. + +```bash +$ cd themes +$ git clone THEME_REPO_URL +``` + +Cloning the repository using Git or another VCS will allow you to easily +update. Alternatively, you can download the files manually and place +them in a folder. + +You can find a list of themes [here](@/themes/_index.md). + +## Using a theme + +Now that you have the theme in your `themes` directory, you need to tell +Zola to use it by setting the `theme` variable in the +[configuration file](@/getting-started/configuration.md). The theme +name has to be the name of the directory you cloned the theme in. +For example, if you cloned a theme in `themes/simple-blog`, the theme name to use +in the configuration file is `simple-blog`. + +## Customizing a theme + +Any file from the theme can be overridden by creating a file with the same path and name in your `templates` or `static` +directory. Here are a few examples of that, assuming that the theme name is `simple-blog`: + +```plain +templates/pages/post.html -> replace themes/simple-blog/templates/pages/post.html +templates/macros.html -> replace themes/simple-blog/templates/macros.html +static/js/site.js -> replace themes/simple-blog/static/js/site.js +``` + +You can also choose to only override parts of a page if a theme defines some blocks by extending it. If we wanted +to only change a single block from the `post.html` page in the example above, we could do the following: + +``` +{% extends "simple-blog/templates/pages/post.html" %} + +{% block some_block %} +Some custom data +{% endblock %} +``` + +Most themes will also provide some variables that are meant to be overridden. This happens in the `extra` section +of the [configuration file](@/getting-started/configuration.md). +Let's say a theme uses a `show_twitter` variable and sets it to `false` by default. If you want to set it to `true`, +you can update your `config.toml` like so: + +```toml +[extra] +show_twitter = true +``` + +You can modify files directly in the `themes` directory but this will make updating the theme harder and live reload +won't work with these files. diff --git a/content/themes/overview.md b/content/themes/overview.md new file mode 100644 index 0000000..0006684 --- /dev/null +++ b/content/themes/overview.md @@ -0,0 +1,11 @@ ++++ +title = "Overview" +weight = 10 ++++ + +Zola has built-in support for themes that makes it easy to customise and update them. + +All themes can use the full power of Zola, from shortcodes to Sass compilation. + +A list of themes is available [here](@/themes/_index.md). + diff --git a/sass/_search.scss b/sass/_search.scss new file mode 100644 index 0000000..4012e96 --- /dev/null +++ b/sass/_search.scss @@ -0,0 +1,61 @@ +.search-container { + display: none; + + &--is-visible { + display: block; + width: 100%; + } + + #search { + width: 100%; + display: block; + border:none; + border-left: 1px solid $color; + padding:1px 0; + text-align: left; + line-height: $baseline; + font-size: $font-size; + font-family:$font-family; + color:$color; + background:transparent; + } + + #search:focus { + outline:none; + border:none; + } + + .search-results { + &__header { + font-weight: bold; + padding: 1rem 0rem; + } + + &__items { + margin: 0 2vw; + padding: 0; + list-style: circle; + } + + &__item { + margin-bottom: 1rem; + } + + &__teaser { + + } + } +} + +#on_right { + display: block; + text-align: right; + margin-bottom: $baseline; +} + +#search-ico { + font-family: 'FabricMDL2Icons'; + cursor: pointer; + font-size: $baseline; + line-height: 1; +} \ No newline at end of file diff --git a/sass/_variables.scss b/sass/_variables.scss new file mode 100644 index 0000000..2e0529e --- /dev/null +++ b/sass/_variables.scss @@ -0,0 +1,13 @@ +$baseline: 1.5rem; + +$background:#f9f9f9; +$color:#222; + +$links: #00f; +$hover-links:#c00; +$visited-links:#009; + +$font-size: 1.125rem; +$font-family: Segoe UI,system-ui,-apple-system,sans-serif; +$line-height: 1.75; +$code_font: 400 1.125rem/1.75 SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace; \ No newline at end of file diff --git a/sass/fabric-icons-inline.scss b/sass/fabric-icons-inline.scss new file mode 100644 index 0000000..df09918 --- /dev/null +++ b/sass/fabric-icons-inline.scss @@ -0,0 +1,40 @@ +/* + Your use of the content in the files referenced here is subject to the terms of the license at https://aka.ms/fabric-assets-license +*/ +@font-face { + font-family: 'FabricMDL2Icons'; + src: url('data:application/octet-stream;base64,d09GRgABAAAAAAusAA4AAAAAFLgABDXDAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABRAAAAEgAAABgMUZ1H2NtYXAAAAGMAAAAWgAAAYKg2Y81Y3Z0IAAAAegAAAAgAAAAKgnZCa9mcGdtAAACCAAAAPAAAAFZ/J7mjmdhc3AAAAL4AAAADAAAAAwACAAbZ2x5ZgAAAwQAAANyAAAEuLnx29VoZWFkAAAGeAAAADIAAAA2A3zu4GhoZWEAAAasAAAAFQAAACQQAQgDaG10eAAABsQAAAAYAAAAGA+HAaZsb2NhAAAG3AAAABYAAAAWBoYE+m1heHAAAAb0AAAAHQAAACAAJAHEbmFtZQAABxQAAAP3AAAJ+o6N8lFwb3N0AAALDAAAABQAAAAg/1EAgXByZXAAAAsgAAAAiQAAANN4vfIOeJxjYGHfzjiBgZWBgXUWqzEDA6M0hGa+yJDGJMTBysrFyMQIBgxAIMCAAL7BCgoMDs8Z3ulxgPkQkgGsjgXCU2BgAADc3QgGeJxjYGBgZoBgGQZGBhCoAfIYwXwWhgQgLcIgABRhec7wXPG50XO/54df7H5x4mXBO73//xkYsIlKMko8lLgqsVXCUdxL3E5shuBtqMkYgJENu/hIAgCdyyInAAB4nGPQYghlKGBoYFjFyMDYwOzAeIDBAYsIEAAAqhwHlXicXY+/TsNADMZzJLSEJ0A6IZ11KkOViJ3phksk1CUlDOelgNRKpO+AlIXFA8/ibhnzYgjMEf4utr/P+ny/c6f5yXx2nKVHKilWnDfhoNQLDurtmf35IU/vNmVhTNV5VvdlwWoJomtOF/VNsGjI0PWWTG0eH7acLWKXxY7w0nDShk7qbQB2qL/HHeJVPJLFI4QS30/xfYxL+rUsVobTiyasA/des/OoAUzFYxN49BoQf8ikP3VnE+NsOWXbwE5zgkSfygL3RJqE+0uPf/Wgkv+G+23Iv6tB9U3c9Bb0h2HBgrChl2fbUAkaYPkOhPxkxgABAAIACAAK//8AD3icXVNNaBtXEJ55b1dPsl0165UqUOJ1dze7mx+quFrJilwQwgQ3P8UpOGCKUhNfSnrqJb/Q4BcoGAr9CfSUGHpyLr2VJCT0klsv7SVXQ29uySmJCbQr7646byWnpjvsm583b+bNN/OAwX0A7Sv9GnAQAC3DNjzbsO/zP+JH7FFyFvRr/a9/0BaBPg6AMg85OgAFKMJR+CWzctCOPwY48ATegtzrJzAGnNZ8Juskz7yPdtMuG2+WPPwD//26lDIGKRmurQFTifJE4EKL8tUtrVwqaq7jB5ijtdloYQ2bjY5m1jus2agx1ymycslienf1wcbti/X6xdsbD1ZvbV+KX5jVqm/yA+cvDG3Xn230ehvPro94Hobm4bEL5+OXpl+tmty4tH1raNuFfe4Zp8olSEFE9U9CFYLsjozqCoxGh4VI4NEfEtnoEpquUSHRsAUcrLmlaHu75NYOIsWJCbeESkfJQO6CvPsZJ1lItR/JP/W7yj8BJndlKhEGhHtCR/r37jFIYdgPCdS0vOqHIOwBVSLTLmTcEBBJreehl26hTCGW+lbfy9NZ9KKeTkhHFAPf4D0OUEBRwKCArQJWtDv8izsxEfFsIZUuvV+NlQtAhgkImgwKMw4GVEY3IQRCMww8ewSKQoEqTYH3UEpvczOWzBtAQppGNSZSA21r10OZIy2Vm1sIfckIlL5Us6fCMwnvwTn4fIR6qchc26mxwC7yTGiqHti0VbE7PEQakVY2NLMfYE15DEeFPEazoywirL9TLuWOo8XD3NP5K8thuHxlfgDty0tzE+nribmly+0BzF9drteXr87j0I4TmT2WVnvm8NjDqu9XH44dnmlbAziy0LCsxsIRXe5JA/i/F5Mqh4rpn1o5eXLllK9iq9x7egqTzokpGkh/6oQzqaLsRVN8/x4gfgoi96GI1NMsMNVAtsijWLziIo5eCZJiscMFFzv0HiWwPIhf4W0wqVM+1FW3iAQaNDg50VS8hUYL9SHGOYG6iR2szDYbvuuQKlqcusXenU7WeJd3F+YSme6w038n371MHqd/6c+PnZmdtg4lYbq+wn6fOt0rH50uVseSj5x1HLBPsBt/n75Yw672Mf6YrqY7485P6dM00JbSn7/EdvLtDVz8JpVW88yx4CxFWcGb7LepQ1HZmg4KFGXdgX8Bg/8uhAAAeJxjYGRgYGAxPVwnx6UQz2/zlYGbgwEE9v892ACi78Sumg+iORjA4pwMTCAKAB/CCRAAAHicY2BkYOBgAAE4yciACpgAAsoAHQAAAAUqAKYIAAAAAAAAgACAAAAAgAAAAV0AgAAAABYASACYAN4BAAEiAVQB4gH4AlwAAHicY2BkYGDgYshiYGUAAUYwyQXCjJEgJgAOogDqAAAAeJy1VE+LGzcUf1472S1plhIo5KhDKZvFjLNuIDQ5LUlzyl42YSGXgjySZ0TGIyFpMkzpoccc+jF6CfRTlBZ67LmfoOeeeux7bzReb+yGbaEeRvPT0/v7e08GgLujz2EE/e8LfHs8gju46/Ee7MNXCY9R/jzhCeKvE74BH4NL+CZ8At8mvA9fwvcJH8Cn8EvCt+AYfk/49ujn0SThQzje+xWjjCYf4U7t/ZnwCD4bXyS8B4fjbxIeo/xtwhPEPyZ8A+6Of0v4JojxHwnvg58cJHwAx5PBzy14Ofkh4dvjt5O/Ej6Elwff/fROzO+fPBRnJvc22GUUT6x31stobJ2J06oS56YoYxDnOmj/RqvsmVx4k4uzp8/n4jQEHcO5LppK+u2DbcmF9gE9iwfZ/KQ/pcP+7IUurBYmCCmil0qvpH8t7FLEUm/kV3jbOBLnduVkbXTIdiZfxugezWZt22ar4TxDm1nsnC28dGU3W9o6htmleWicq4xWgg4y8co2YiU70QSNSWBiJBbRitxrGfVUKBNcJbupkLUSzhs8zVFF41cG4bRfmRjR3aLjIiqT65p84UEQ1g9gSRGm26U6b1WTx6kg5tF2SjZDAFOLtjR5uZFZi0FNnVeNwjats7d11Ykjc0/o1QJzuVRHDx/KltWVqQvhdYjYKWL1MgCZr309ZgaODEaJekUt8AajKtvWlZXqKnuyp0p7KsdiKFyb6JoolKYySafUlbvKKA5j3SV1agg6RH5KszCYc3b9bsM7EDCH+3ACDxGdgYEcPFgI+C4houwJIo93nlaJEoOohgxPTqHCR8A5ygoo8SzwTuNXo/YbXBVqPkO7Be7JN8V4iv8sc7YPrEl2ZFVAg/4kal7H4jo6F5xHSDkLeIDZzLHWTdvBctPuBWdjcRWoQ1VJfCMzoFC64ixfo4xYopOSdXfxV/C+QQYH7Ry/K9xLzMkwW9m/YJ54jih9BDN8Wn4y9Pe+fZbizBB37KVgPw49dChdsjeqdrYzeuCcHXbEcB/F2oJ6/4prEsxEh9+GueuZ6BkbtElmuWqPGlSHhinuFes57njHEuKD4jjuTG+bJy867SX7dtxXqjnyGVktOI+hExVXRFZDXr1F4C74LclyXcP0Wl11vFdok+N+ynz1M9/Hna7jvF+B4Ulsmacc192ctalS0s6xmobnTu3knmwqRkeofw+/NKGLxMsu730O/5XbS++KPRUo8zzHMd2pYVZ3VTBE387r8cYMUCV9LZHjDbeA/Pe1KpS0XLnlW/mh2ZNXpkpzX2xa+6p63PDNatiSsh26OfghzYpv8j/PaP/PWKfOXHofbohJLNP8UL4LZrrv7f9wt/8GD0U4iAB4nGNgZgCD/34M5QyYgAsAKTQB0nic28CgzbCJkZNJm3ETF4jcztWaG2qrysChvZ07NdhBTwbE4onwsNCQBLF4nc215YVBLD4dFRkRHhCLX05CmI8DxBLg4+FkZwGxBMEAxBLaMKEgwADIYtjOCDeaCW40M9xoFrjRrHCj2eQkoUazw43mgBvNCTd6kzAju/YGBgXX2kwJFwDEASgaAAAA') format('truetype'); +} + +.ms-Icon { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-family: 'FabricMDL2Icons'; + font-style: normal; + font-weight: normal; + speak: none; +} + +// Mixins +@mixin ms-Icon--ChevronRightSmall { content: "\E970"; } +@mixin ms-Icon--ChromeClose { content: "\E8BB"; } +@mixin ms-Icon--Copy { content: "\E8C8"; } +@mixin ms-Icon--GlobalNavButton { content: "\E700"; } +@mixin ms-Icon--MiniLink { content: "\E732"; } +@mixin ms-Icon--Page { content: "\E7C3"; } +@mixin ms-Icon--ProductRelease { content: "\EE2E"; } +@mixin ms-Icon--Save { content: "\E74E"; } +@mixin ms-Icon--Search { content: "\E721"; } + + +// Classes +.ms-Icon--ChevronRightSmall:before { @include ms-Icon--ChevronRightSmall } +.ms-Icon--ChromeClose:before { @include ms-Icon--ChromeClose } +.ms-Icon--Copy:before { @include ms-Icon--Copy } +.ms-Icon--GlobalNavButton:before { @include ms-Icon--GlobalNavButton } +.ms-Icon--MiniLink:before { @include ms-Icon--MiniLink } +.ms-Icon--Page:before { @include ms-Icon--Page } +.ms-Icon--ProductRelease:before { @include ms-Icon--ProductRelease } +.ms-Icon--Save:before { @include ms-Icon--Save } +.ms-Icon--Search:before { @include ms-Icon--Search } \ No newline at end of file diff --git a/sass/main.scss b/sass/main.scss new file mode 100644 index 0000000..f335bb5 --- /dev/null +++ b/sass/main.scss @@ -0,0 +1,342 @@ +@import "variables"; + +html { + font-kerning: normal; + text-rendering: optimizeLegibility; + scroll-behavior: smooth; +} + +body { + margin:$baseline 0; + font-size:$font-size; + font-family:$font-family; + line-height: $line-height; + background:$background; + color:$color; +} + +@keyframes fade-in { + 0% { + opacity: 0; + } + + 50% { + opacity: 0.8; + } + + 100% { + opacity: 1; + } +} + +a { + &:link { + color:$links; + text-decoration: none; + } + + &:hover { + color:$hover-links; + } + + &:visited { + color:$visited-links; + } +} + +h2, +h3, +h4 { + .anchor { + visibility: hidden; + text-decoration: none; + cursor: pointer; + line-height: 1; + color:$color; + } + + &:hover { + .anchor { + visibility: visible; + animation: fade-in 0.3s ease-in-out; + font-family: 'FabricMDL2Icons'; + } + } +} + +pre { + margin:$baseline 0; + border-radius: 4px; + padding:$baseline; + overflow: auto; + position: relative; + + code { + background:transparent; + + &::after { + content: attr(data-lang); + font-style: italic; + line-height: 1; + opacity:0.3; + position:absolute; + bottom:$baseline; + right:$baseline; + z-index:1; + } + } +} + + code { + font: $code_font; + } + + .copy-code-button { + font-family: 'FabricMDL2Icons'; + display:none; + background:$background; + border-radius: 4px; + border:none; + cursor: pointer; + animation: fade-in 0.3s ease-in-out; + font-size: $baseline; + color:$color; + z-index: 10; + position:absolute; + top:$baseline; + right:$baseline; + } + + pre:hover .copy-code-button { + display: block; + } + +nav { + position: sticky; + height: 92vh; + top:$baseline; + left:$baseline; + bottom: $baseline; + padding-right: $baseline; + width: 20rem; + + img { + width:128px; + } + + h1 { + margin:0; + line-height: 1; + } +} + +#toc { + margin-left:calc(#{$baseline} + #{$font-size}); + padding:0; + margin:0 0 0 $baseline; + font-size: 80%; + + li { + color:$color; + margin-left: $font-size; + + &::before { + display: inline-block; + content:""; + } + + ul { + padding:0; + } + +} + +} + +main { + display: flex; + flex-flow: row nowrap; + animation: fade-in 0.4s ease-in-out; +} + +#release { + text-align: left; + margin:$baseline 0; + +&::before { + display: inline-block; + content: "\EE2E"; + font-family: 'FabricMDL2Icons'; + margin-right:calc(#{$baseline} / 8); +} +} + +@keyframes slideIn { + 0% { + max-height:0; + opacity:0 + } + 100% { + max-height:999px; + opacity:1 + } + } + @keyframes slideOut { + 0% { + height:auto; + opacity:1 + } + 100% { + height:0; + opacity:0 + } + } + + nav label { + display:block; + } + + #trees { + overflow-y: auto; + height: 80%; + } + + .subtree { + overflow:hidden; + margin:calc(#{$baseline} / 8) 0; + transition: overflow 0.2s ease-in-out; + padding: 0; + } + + .tree-toggle-label { + user-select:none; + cursor:pointer; + } + + .tree-toggle-label::before { + display:inline-block; + content:"\E970"; + font-family:'FabricMDL2Icons'; + font-size:.75rem; + transform:rotate(0deg); + transform-origin:50% 50% 0px; + transition:transform 0.1s linear 0s; + margin-right: 2px; + } + + + .tree-toggle { + position:absolute; + opacity:0; + z-index:-1; + } + + .tree-toggle:checked+.tree-toggle-label::before { + content:"\E970"; + font-family:'FabricMDL2Icons'; + font-size:.75rem; + transform:rotate(90deg); + transform-origin:50% 50% 0px; + transition:transform 0.1s linear 0s; + margin-right: 2px; + } + + .tree-toggle:checked+.tree-toggle-label { + font-weight:bold; + } + + .tree-toggle+.tree-toggle-label+.subtree { + animation-name:slideOut; + animation-duration:0.25s; + animation-fill-mode:both; + } + + .tree-toggle:checked+.tree-toggle-label+.subtree { + animation-name:slideIn; + animation-duration:0.25s; + animation-fill-mode:both; + } + + + .subtree li { + list-style-type: none; + margin-left: $baseline; + + + a { + color:$color; + } + + &::before { + content: "\E7C3"; + font-family:'FabricMDL2Icons'; + font-size:0.75rem; + } + +} + +.active a { + font-weight: bold; +} + + +article { + width: calc(100% - (#{$baseline} * 4 + 20rem)); + margin-left:calc(#{$baseline} * 2); + + img { + max-width:100%; + } + +} + +#mobile { + display: none; +} + + +@media screen and (max-width: 1023px) { + + main { + flex-flow: column nowrap; + width: 100%; + } + + nav { + position: inherit; + height:auto; + margin:$baseline $baseline 0 $baseline; + } + + article { + width: calc(100% - (#{$baseline} * 2)); + margin:0 $baseline; + z-index:1; + } + + #mobile { + font-family: 'FabricMDL2Icons'; + cursor: pointer; + font-size: $baseline; + margin:0 $baseline 0 0; + display: block; + color:$color; + } + + #trees { + display: none; + position:absolute; + background: $background; + height:auto; + width:100vw; + z-index:10; + box-shadow: 0 2px 0 rgba(0,0,0,.1); + } + + #on_right { + margin-top:$baseline; + } +} + +@import "fabric-icons-inline"; +@import "search"; \ No newline at end of file diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000..fd7496a Binary files /dev/null and b/screenshot.png differ diff --git a/static/js.js b/static/js.js new file mode 100644 index 0000000..4769a10 --- /dev/null +++ b/static/js.js @@ -0,0 +1,295 @@ +// search script, borrowed from book theme + +function debounce(func, wait) { + var timeout; + + return function () { + var context = this; + var args = arguments; + clearTimeout(timeout); + + timeout = setTimeout(function () { + timeout = null; + func.apply(context, args); + }, wait); + }; + } + + // Taken from mdbook + // The strategy is as follows: + // First, assign a value to each word in the document: + // Words that correspond to search terms (stemmer aware): 40 + // Normal words: 2 + // First word in a sentence: 8 + // Then use a sliding window with a constant number of words and count the + // sum of the values of the words within the window. Then use the window that got the + // maximum sum. If there are multiple maximas, then get the last one. + // Enclose the terms in . + function makeTeaser(body, terms) { + var TERM_WEIGHT = 40; + var NORMAL_WORD_WEIGHT = 2; + var FIRST_WORD_WEIGHT = 8; + var TEASER_MAX_WORDS = 30; + + var stemmedTerms = terms.map(function (w) { + return elasticlunr.stemmer(w.toLowerCase()); + }); + var termFound = false; + var index = 0; + var weighted = []; // contains elements of ["word", weight, index_in_document] + + // split in sentences, then words + var sentences = body.toLowerCase().split(". "); + + for (var i in sentences) { + var words = sentences[i].split(" "); + var value = FIRST_WORD_WEIGHT; + + for (var j in words) { + var word = words[j]; + + if (word.length > 0) { + for (var k in stemmedTerms) { + if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) { + value = TERM_WEIGHT; + termFound = true; + } + } + weighted.push([word, value, index]); + value = NORMAL_WORD_WEIGHT; + } + + index += word.length; + index += 1; // ' ' or '.' if last word in sentence + } + + index += 1; // because we split at a two-char boundary '. ' + } + + if (weighted.length === 0) { + return body; + } + + var windowWeights = []; + var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS); + // We add a window with all the weights first + var curSum = 0; + for (var i = 0; i < windowSize; i++) { + curSum += weighted[i][1]; + } + windowWeights.push(curSum); + + for (var i = 0; i < weighted.length - windowSize; i++) { + curSum -= weighted[i][1]; + curSum += weighted[i + windowSize][1]; + windowWeights.push(curSum); + } + + // If we didn't find the term, just pick the first window + var maxSumIndex = 0; + if (termFound) { + var maxFound = 0; + // backwards + for (var i = windowWeights.length - 1; i >= 0; i--) { + if (windowWeights[i] > maxFound) { + maxFound = windowWeights[i]; + maxSumIndex = i; + } + } + } + + var teaser = []; + var startIndex = weighted[maxSumIndex][2]; + for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) { + var word = weighted[i]; + if (startIndex < word[2]) { + // missing text from index to start of `word` + teaser.push(body.substring(startIndex, word[2])); + startIndex = word[2]; + } + + // add around search terms + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + startIndex = word[2] + word[0].length; + teaser.push(body.substring(word[2], startIndex)); + + if (word[1] === TERM_WEIGHT) { + teaser.push(""); + } + } + teaser.push("…"); + return teaser.join(""); + } + + function formatSearchResultItem(item, terms) { + var li = document.createElement("li"); + li.classList.add("search-results__item"); + li.innerHTML = `${item.doc.title}`; + li.innerHTML += `
${makeTeaser(item.doc.body, terms)}
`; + return li; + } + + // Go from the book view to the search view + function toggleSearchMode() { + var $wrapContent = document.querySelector("#wrap"); + var $searchIcon = document.querySelector("#search-ico"); + var $searchContainer = document.querySelector(".search-container"); + if ($searchContainer.classList.contains("search-container--is-visible")) { + $searchContainer.classList.remove("search-container--is-visible"); + $wrapContent.style.display = ""; + $searchIcon.className = "ms-Icon--Search"; + } else { + $searchContainer.classList.add("search-container--is-visible"); + $wrapContent.style.display = "none"; + $searchIcon.className = "ms-Icon--ChromeClose"; + document.getElementById("search").focus(); + } + } + + function initSearch() { + var $searchInput = document.getElementById("search"); + if (!$searchInput) { + return; + } + var $searchIcon = document.querySelector("#search-ico"); + $searchIcon.addEventListener("click", toggleSearchMode); + + var $searchResults = document.querySelector(".search-results"); + var $searchResultsHeader = document.querySelector(".search-results__header"); + var $searchResultsItems = document.querySelector(".search-results__items"); + var MAX_ITEMS = 100; + + var options = { + bool: "AND", + fields: { + title: {boost: 2}, + body: {boost: 1}, + } + }; + var currentTerm = ""; + var index = elasticlunr.Index.load(window.searchIndex); + + $searchInput.addEventListener("keyup", debounce(function() { + var term = $searchInput.value.trim(); + if (term === currentTerm || !index) { + return; + } + $searchResults.style.display = term === "" ? "none" : "block"; + $searchResultsItems.innerHTML = ""; + if (term === "") { + return; + } + + var results = index.search(term, options).filter(function (r) { + return r.doc.body !== ""; + }); + if (results.length === 0) { + $searchResultsHeader.innerText = `Nothing like «${term}»`; + return; + } + + currentTerm = term; + $searchResultsHeader.innerText = `${results.length} found for «${term}»:`; + for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) { + if (!results[i].doc.body) { + continue; + } + // var item = document.createElement("li"); + // item.innerHTML = formatSearchResultItem(results[i], term.split(" ")); + console.log(results[i]); + $searchResultsItems.appendChild(formatSearchResultItem(results[i], term.split(" "))); + } + }, 150)); + } + + if (document.readyState === "complete" || + (document.readyState !== "loading" && !document.documentElement.doScroll) + ) { + initSearch(); + } else { + document.addEventListener("DOMContentLoaded", initSearch); + } + +// mobile + + function burger() { + let x = document.querySelector("#trees"); + let y = document.querySelector("#mobile"); + + if (x.style.display === "block") { + x.style.display = "none"; + y.className = "ms-Icon--GlobalNavButton"; + } else { + x.style.display = "block"; + y.className = "ms-Icon--ChromeClose"; + } + } + +// https://aaronluna.dev/blog/add-copy-button-to-code-blocks-hugo-chroma/ + +function createCopyButton(highlightDiv) { + const button = document.createElement("button"); + button.className = "copy-code-button "; + button.type = "button"; + button.innerHTML = ""; + button.addEventListener("click", () => + copyCodeToClipboard(button, highlightDiv) + ); + addCopyButtonToDom(button, highlightDiv); +} + +async function copyCodeToClipboard(button, highlightDiv) { + const codeToCopy = highlightDiv.querySelector(":last-child > code") + .innerText; + try { + result = await navigator.permissions.query({ name: "clipboard-write" }); + if (result.state == "granted" || result.state == "prompt") { + await navigator.clipboard.writeText(codeToCopy); + } else { + copyCodeBlockExecCommand(codeToCopy, highlightDiv); + } + } catch (_) { + copyCodeBlockExecCommand(codeToCopy, highlightDiv); + } finally { + codeWasCopied(button); + } +} + +function copyCodeBlockExecCommand(codeToCopy, highlightDiv) { + const textArea = document.createElement("textArea"); + textArea.contentEditable = "true"; + textArea.readOnly = "false"; + textArea.className = "copyable-text-area"; + textArea.value = codeToCopy; + highlightDiv.insertBefore(textArea, highlightDiv.firstChild); + const range = document.createRange(); + range.selectNodeContents(textArea); + const sel = window.getSelection(); + sel.removeAllRanges(); + sel.addRange(range); + textArea.setSelectionRange(0, 999999); + document.execCommand("copy"); + highlightDiv.removeChild(textArea); +} + +function codeWasCopied(button) { + button.blur(); + button.innerHTML = ""; + setTimeout(function () { + button.innerHTML = ""; + }, 2000); +} + +function addCopyButtonToDom(button, highlightDiv) { + highlightDiv.insertBefore(button, highlightDiv.firstChild); + const wrapper = document.createElement("div"); + wrapper.className = "highlight-wrapper"; + highlightDiv.parentNode.insertBefore(wrapper, highlightDiv); + wrapper.appendChild(highlightDiv); +} + +document + .querySelectorAll("pre") + .forEach((highlightDiv) => createCopyButton(highlightDiv)); diff --git a/static/logo.svg b/static/logo.svg new file mode 100644 index 0000000..5d7d965 --- /dev/null +++ b/static/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/anchor-link.html b/templates/anchor-link.html new file mode 100644 index 0000000..f123e20 --- /dev/null +++ b/templates/anchor-link.html @@ -0,0 +1 @@ +  \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..041abbe --- /dev/null +++ b/templates/index.html @@ -0,0 +1,137 @@ + + + + + + {% if config.extra.favicon %} + + {% endif %} + + {% block title %}{{ config.title }}{% endblock title %} + + + + {% if config.extra.release %} + + {% endif %} +
+ + {% block nav %} + + + {% endblock nav %} + +
+ + {% if config.build_search_index %} +
+ +
+
+ +
+
+
    +
    +
    + {% endif %} + +
    + {% block content %} + {{ section.content | safe }} + {% endblock content %} +
    + +
    +
    + + {% if config.build_search_index %} + + + + {% endif %} + + + diff --git a/templates/page.html b/templates/page.html new file mode 100644 index 0000000..c836720 --- /dev/null +++ b/templates/page.html @@ -0,0 +1,5 @@ +{% extends "index.html" %} +{% block title %} {{ config.title }} | {{ page.title }} {% endblock title %} + {% block content %} + {{ page.content | safe }} + {% endblock content %} \ No newline at end of file diff --git a/theme.toml b/theme.toml new file mode 100644 index 0000000..2649a5b --- /dev/null +++ b/theme.toml @@ -0,0 +1,10 @@ +name = "EasyDocs" +description = "An easy way to create docs for your project" +license = "MIT" +homepage = "https://github.com/codeandmedia/zola_easydocs_theme" +min_version = "0.13.0" +demo = "https://easydocs.codeandmedia.com" + +[author] +name = "Roman Soldatenkov" +homepage = "https://codeandmedia.com" \ No newline at end of file