sqzass.git

sqzass

~ A static site generator written in Rust
git clone https://github.com/debuman/sqzass.git

docs/content/templates/functions.md (3506B)

      1 +++
      2 title = "Functions and filters"
      3 description = "Everything a template can call, and the closing line that nothing else exists"
      4 weight = 40
      5 toc = true
      6 +++
      7 
      8 ## Provided by sqzass
      9 
     10 Two functions. That is the whole list.
     11 
     12 ### asset(path)
     13 
     14 Returns the URL a static file was written to, hash and subpath included.
     15 
     16 ```html
     17 <link rel="stylesheet" href="{{ asset("css/main.css") }}">
     18 <script src="{{ asset("js/search.js") }}" defer></script>
     19 ```
     20 
     21 The argument is the logical path under `static/`, with or without a leading
     22 slash. A name that was not collected is a build error listing every name that
     23 was — a renamed stylesheet fails the build instead of 404ing for every visitor.
     24 
     25 ### t(key)
     26 
     27 Looks a UI string up in `i18n/<language>.toml`, for the language of the page
     28 being rendered.
     29 
     30 ```html
     31 <a class="skip" href="#content">{{ t("skip_to_content") }}</a>
     32 ```
     33 
     34 One argument. The language is never passed in — see
     35 [Languages](@/content/languages.md) for why that is deliberate. A key missing
     36 from the current language is a build error.
     37 
     38 > [!WARNING]
     39 > Do not name a loop variable `t`. `{% for t in page.translations %}` shadows
     40 > the function inside that block, and the first person to add a label there gets
     41 > an error a long way from its cause.
     42 
     43 ## From minijinja
     44 
     45 Standard Jinja2 syntax works: `{% if %}`, `{% for %}`, `{% extends %}`,
     46 `{% block %}`, `{% include %}`, `{% macro %}`, `{% from … import … %}`, `{% set %}`,
     47 and the usual filters — `safe`, `escape`, `length`, `join`, `default`, `upper`,
     48 `lower`, `replace`, `trim`, `first`, `last`, `reverse`, `sort`, `map`,
     49 `select`, `selectattr`, `batch`, `slice`, `int`, `float`, `abs`, `round`,
     50 `indent`.
     51 
     52 Our own templates use `{% macro %}` and `{% from "partials/sidebar.html" import nav %}`,
     53 so those two are exercised on every build.
     54 
     55 Three filters a Jinja2 habit reaches for are **not** here: `tojson`,
     56 `urlencode` and `striptags`. Each is behind a minijinja feature we leave off,
     57 and each is a dependency for something already covered — a `{% for %}` loop, a
     58 URL that arrives ready to use, or markup you did not have to strip because you
     59 wrote it. Calling one is a build error, not an empty string, so you find out at
     60 build time rather than in the page.
     61 
     62 ## Nothing else exists
     63 
     64 There is no `url_for`, no `markdownify`, no `date`, no `now()`, no `env()`, no
     65 custom tests. Some of those are absences with reasons rather than gaps:
     66 
     67 `now()` and `env()` would break the guarantee that two builds of the same input
     68 produce identical bytes, which CI checks on every push. A template that can read
     69 the clock cannot be reproducible.
     70 
     71 `url_for` would wrap a comparison that is already one line. Page and section
     72 URLs arrive ready to use, and they already carry the subpath.
     73 
     74 Reading a name that does not exist is a build error, not an empty string — so
     75 if you call something from another generator by habit, you find out at build
     76 time rather than from a page with a hole in it.
     77 
     78 ## Marking the current page
     79 
     80 There is no helper for this, and none is needed. Exact match for a page:
     81 
     82 ```html
     83 <a href="{{ p.url }}"{% if p.url == page.url %} aria-current="page"{% endif %}>{{ p.title }}</a>
     84 ```
     85 
     86 Ancestor match for a section, using `page.section`:
     87 
     88 ```html
     89 <a href="{{ s.url }}"{% if page.section and page.section.url == s.url %} aria-current="true"{% endif %}>{{ s.title }}</a>
     90 ```
     91 
     92 For a prefix test use `startingwith`, but be careful with the root: every URL
     93 starts with `/`, so the home link must be compared exactly and never as an
     94 ancestor.