Notes for Programmers

This wiki is powered by Eleventy, a static site generator. The templating language is Liquid with the additional filters and tags that Jekyll provides: the site was built with Jekyll before, and a compatibility layer keeps its templates working (site.data, page.title, {% include a.html x=y %}, kramdown-style markdown). See docs/ELEVENTY.md for the details.

To preview the site locally, install Node.js and pnpm, run pnpm install, then pnpm eleventy:dev and open the address it prints. pnpm test runs the unit tests of the plugins.

I swear to god that Jekyll/Liquid’s documentation is a lot easier to understand than SemanticWiki’s documentation, so please read.

For code change that affects significant parts of the website (excluding trivial bug fixes), please open a new Pull Request instead of directly commiting to the master branch.

For code change related to website design, please include screenshot preview whenever possible.

Code convention

You can use any modern HTML/CSS/JS features you like. Bootstrap and JQuery are banned, other dependencies can be considered.

We do most of the content processing and rendering in Liquid and the JavaScript plugins so that the content is ready as soon as web browser downloads a page. However, if certain feature is too difficult to implement in Liquid or it is not neccessary to load as soon as possible, it is good to embed some information as data-* attribute in some HTML elements and do more processing in client-side JS. Think: progressive enhancement.

Random things about Liquid templating

  1. To enumerate all objects in a map/dictionary (e.g. {"a": 1, "b": b}), do this:

    {% for pair in obj_map %}
    {{ pair[0] }} is key, {{ pair[1] }} is value
    {% endfor %}
    
  2. To access parameters passed to a template, use include.varname. Example:

    # Somewhere in a .md file
    {% include awesome-tmpl.html username="Alex" %}
    
    # In `_includes/awesome-tmpl.html`
    Username: {{ include.username }}
    
  3. Comment syntax in Liquid is {% comment %}blah blah{% endcomment %}.

  4. Key of map/dictionary is type sensitive. {1: "hello", 2: "world"} uses integer as key. {"1": "hello", "2": "world"} string as key. Make sure you the key is in correct type when you do {% assign value = obj_map[key] %}.

  5. To convert string into integer, use {% assign x_int = x_str | plus: 0 %}.

  6. To convert integer into string, use {% assign x_str = x_int | downcase %}.

  7. You cannot re-assign to variable used in the for loop enumeration, in another words this is not allowed:

    {% for flower in flowers %}
    {% assign flower = flower | upcase %} # `flower` still won't be changed
    {% endfor %}
    

    Instead create a new variable:

    {% for flower in flowers %}
    {% assign f = flower | upcase %}
    {% endfor %}