First check-in of "Elf's Notes"

This is the initial checkin of my notes site. It's mostly a cheat-sheet format,
with two different strands:

1. A reference sheet of commands in the order that matters to *me*, i.e. the
   things I use most, or forget most often, appear at the top of the documents.

2. A collection of recipes for getting common tasks completed.  Basically, my
   cookbook of things that I care about
This commit is contained in:
Elf M. Sternberg 2022-04-24 17:22:51 -07:00
commit 0c8765a514
66 changed files with 444 additions and 0 deletions

16
config.toml Normal file
View File

@ -0,0 +1,16 @@
# The URL the site will be built for
base_url = "https://elfsternberg.com/notes"
# Whether to automatically compile all Sass files in the sass directory
compile_sass = true
# Whether to build a search index to be used later on by a JavaScript library
build_search_index = true
[markdown]
# Whether to do syntax highlighting
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
highlight_code = true
[extra]
# Put all your custom variables here

19
content/_index.md Normal file
View File

@ -0,0 +1,19 @@
+++
title = "Elf's Notes"
# The homepage contents
[extra]
lead = "This is Elf Sternberg's brain dump of notes about various software things he knows. If you find it useful, good! Just be aware that this site is probably a bit random, as it consists of explanations, snippets, and recipes for how I do things. It's meant to be a guide from a past version of myself to explain things to a future version that may have forgotten."
# Menu items
[[extra.menu.main]]
name = "Blog"
section = "blog"
url = "https://elfsternberg.com"
weight = 20
[[extra.list]]
title = "Zola"
url="/docs/zola"
content = 'This site is hosted with <a href="https://getzola.org">Zola</a>, a static site generator written in Rust.'
+++

177
content/docs/zola/_index.md Normal file
View File

@ -0,0 +1,177 @@
+++
title = "Zola"
description = "Zola is a static site generator"
date = 2025-05-01T18:00:00+00:00
updated = 2021-05-01T18:00:00+00:00
template = "section.html"
sort_by = "weight"
weight = 4
draft = false
+++
# Zola
[Zola](https://getzola.org) is a static site generator written in
[Rust](../rust). It builds an entire web page out of a structured markdown
collection and a collection of HTML templates. The templating language is called
[Tera](https://tera.netlify.app).
## Running Zola
- `zola init` - Starts a new Zola project. Not for the faint of heart.
- `zola serve` - Starts a localhost webserver to serve your content for demo
- `zola build` - Builds a Zola project into a collection of static HTML.
## Project layout
The following files and folders define a basic Zola project
- `config.toml`: A configuration file in the [TOML](https://toml.io/en/)
configuration language. Can contain a lot of information that will be made
available to *all* pages in the system.
- `content/`: The structured content folder.
- `sass/`: [Sass](../sass) is a CSS preprocessor language that makes CSS easier.
- `static/`: Static content such as images, fonts, and Javascript
- `templates`: The HTML templates (and includes, etc) that define the website's
layouts
Note that if you want to use modern Javascript features such as a precompiler
like Typescript or a bundler like Webpack, that is outside the functionality of
Zola. You'll have to have a separate project for that, or a subfolder or git
submodule, and you'll have to have a separate build step for that.
It's also a bit of a shame that Tera is 100% an HTML play, and there's no HAML
or similar HTML templating involved. That would be a nifty project.
## Tera
The Tera templating language looks a lot like Django's, or for that matter any
number of templating languages. Every page generated with Tera receives a
_context_, which can be thought of as a JSON object with which to populate the
page (it is, technically, a [Serde::Serializable](https://serde.rs/)). Zola
provides a large and complex context, which is explained further down.
Tera has the following syntax. Everything within these markers is processed by
Tera; everything outside is left untouched.
- `{{` and `}}` for expressions
- `{%` and `%}` for statements
- `{#` and `#}` for comments
Statements that have a dash as part of their delimeter remove all whitespace
from around the delimiter. `{%-` says to eliminate all whitespace between this
statement and anything that came before it; `-%}` says to eliminate everything
that comes after it.
### Statements
#### `set`
Variables are set in a given scope with `set`:
```jinja2
{% set my_var = "hello" %}
```
Sets a variable `my_var`. Variables can contain booleans, floats, strings,
integers, and arrays. There is a special syntax, `set_global`, that can be used
to set variables one level up in scope when working inside `for` loops (i.e. in
the outer scope containing the loop, preserving its content between iterations).
#### `if`
Conditional statements are managed with `if/is ... else ... endif`
```jinja2
{% if my_var is ... %} ... {% endif %}
```
The list of `is` tests that are shipped with Zola are:
- `defined`: the given variable is defined.
- `undefined`: the given variable is undefined.
- `odd`: the given variable is an odd number.
- `even`: the given variable is an even number.
- `string`: the given variable is a string.
- `number`: the given variable is a number.
- `divisibleby`: the given expression is divisible by the arg given.
- `iterable`: Returns true if the given variable can be iterated over in Tera (i.e. is an array/tuple or an object).
- `object`: Returns true if the given variable is an object (i.e. can be iterated over key, value).
- `starting_with(string)`: Returns true if the given variable is a string and starts with the arg given.
- `ending_with(string)`: Returns true if the given variable is a string and ends with the arg given.
- `containing(val)`: Returns true if the given variable contains the arg given.
- strings: is the arg a substring?
- arrays: is the arg given one of the members of the array?
- maps: is the arg given a key of the map?
- `matching(regexp)`: Returns true if the given variable is a string and matches the regex in the argument.
#### `for`
Arrays are iterated with the `for x in array/map ... endfor` syntax.
```jinja2
{% for name in users %}
Hello: {{ name }}
{% endfor %}
```
Maps will provide a key/value pair. The names of the two fields are arbitrary:
```jinja2
{% for name, label in options %}
<option value="{name}">{label}</option>
{% endfor %}
```
Array filters (see below) are invoked before the loop. The following will print
the list in reverse order.
```jinja2
{% for name in users | reverse %}{{ name }}{% endfor %}
```
#### `include`
Include other content into the current template being rendered. Include strings
cannot be built out of variables, but they _may_ be a list, in which case the
first filename found is rendered. If the include block has the phrase 'ignore
missing' at the end a missing file will not cause an error at build time.
```jinja2
{% include "header.html" %}
```
#### Macros
Macros are blocks of template that can be passed variables; they're basically
just big chunks of content that can be parameterized. Macros must be defined in
a file separate from the main content and imported with a distinct syntax from
`import`:
```jinja2
{% import "header.html" as header %}
```
The header macro can be invoked in that file like this:
```jinja2
{{ header::header("My Blog!") }}
```
And an example of this macro (again, in the `header.html` file) would look like this:
```jinja2
{% macro header(title) %}
<header class="header">
<h1>{ title }</h1>
</header>
{% endmacro %}
```
```jinja2
{% raw %}Content {{ goes here }}{% endraw %}
```
Content within the `raw` block will not be processed.

25
hold/index.md Normal file
View File

@ -0,0 +1,25 @@
[[extra.list]]
title = "React ⚛"
url="/docs/react"
content = 'React is a library for writing responsive web pages. Professionally, I write React, and I write a lot of it.'
[[extra.list]]
title = "Typescript"
url="/docs/typescript"
content = "Typescript is a superset of Javascript that provides a language of types and type flow. It's my preferred front-end language."
[[extra.list]]
title = "CSS"
url="/docs/css"
content = "CSS is the language of styles for web development."
[[extra.list]]
title = "Sass"
url="/docs/sass"
content = "Sass is a high-level language that compiles down to CSS."
[[extra.list]]
title = "Rust"
url="/docs/rust"
content = "Rust is a system programming language that provides the speed of C/C++, but imposes a strict discipline on memory management that creates much safer and more reliable code."

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

26
templates/base.html Normal file
View File

@ -0,0 +1,26 @@
{%- import 'macros/font_preloads.html' as font_preloads -%}
{%- import 'macros/stylesheets.html' as stylesheets -%}
{%- import 'macros/header.html' as header -%}
{%- import 'macros/footer.html' as footer -%}
<!DOCTYPE html>
<html lang="{{ config.extra.language_code | default(value="en-US") }}">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{{ font_preloads::preloads() }}
{{ stylesheets::stylesheets() }}
</head>
{% block body %}{% set page_class="home" %}{% endblock body %}
<body class="{{ page_class }}">
{% block header %}
{{ header::header(current_section="/") }}
{% endblock header %}
{% block content %}{% endblock content %}
{% block footer %}
{{ footer::footer() }}
{% endblock footer %}
</body>
</html>

View File

@ -0,0 +1,48 @@
{% extends "section.html" %}
{% block body %}
{% set page_class = "docs list" %}
{% endblock body %}
{% block header %}
{% set current_section = "docs" %}
{{ macros_header::header(current_section=current_section)}}
{% endblock header %}
{% block content %}
<div class="wrap container" role="document">
<div class="content">
<div class="row justify-content-center">
<div class="col-md-12 col-lg-10 col-xxl-8">
<article>
<h1 class="text-center">{{ section.title }}</h1>
<div class="text-center">{{ section.content | safe }}</div>
<div class="card-list">
{% set index_path = current_path ~ "_index.md" | trim_start_matches(pat="/") %}
{% set index = get_section(path=index_path) %}
{% for page in index.pages %}
<div class="card my-3">
<div class="card-body">
<a class="stretched-link" href="{{ page.permalink }}">{{ page.title }} &rarr;</a>
</div>
</div>
{% endfor %}
{% for s in index.subsections %}
{% set subsection = get_section(path=s) %}
{% if subsection.pages %}
{% for page in subsection.pages %}
<div class="card my-3">
<div class="card-body">
<a class="stretched-link" href="{{ page.permalink }}">{{ page.title }} &rarr;</a>
</div>
</div>
{% endfor %}
{% endif %}
{% endfor %}
</div>
</article>
</div>
</div>
</div>
</div>
{% endblock content %}

34
templates/index.html Normal file
View File

@ -0,0 +1,34 @@
{% extends "base.html" %}
{% block content %}
<div class="container" role="document">
<div class="content">
<section class="section container-fluid mt-n3 pb-3">
<div class="row justify-content-center">
<div class="col-lg-12 text-center">
<h1>{{ section.title | default(value="Elf's Notes") }}</h1>
</div>
<div class="col-lg-9 col-xl-8 text-center">
<p class="lead">
{{ section.extra.lead | default(value="Please start setting config.toml and adding
your content.") | safe }}
</p>
</div>
</div>
</section>
</div>
</div>
<section class="section section-sm">
<div class="container">
<div class="topic-cards">
{% if section.extra.list %} {% for val in section.extra.list %}
<div class="topic-card">
<h2>{{ val.title }}</h2>
<p>{{ val.content | safe }}</p>
</div>
{% endfor %} {% endif %}
</div>
</div>
</section>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% macro preloads() %}
{% if config.extra.preloads %}
{% for preload in config.extra.preloads %}
<link
rel="preload"
as="font"
href="{{ get_url(path="{{ preload }}") | safe }}"
type="{% if preload is ending_with(".woff2") %}font/woff2{% else %}font/woff{% endif %}"
crossorigin />
{% endfor %}
{% endif %}
{% endmacro %}

View File

@ -0,0 +1,24 @@
{% macro footer() %}
<footer class="footer">
<div class="container">
<div class="row">
<div class="col-lg-8 order-last order-lg-first">
<ul class="list-inline">
<li class="list-inline-item">
Elf's Notes are copyright (C) 2008-2022 Elf M. Sternberg
</li>
</ul>
</div>
<div class="col-lg-8 order-first order-lg-last text-lg-end">
<ul class="list-inline">
{% if config.extra.footer.nav %} {%- for val in config.extra.footer.nav -%}
<li class="list-inline-item">
<a href="{{ get_url(path=val.url, trailing_slash=true) | safe }}">{{ val.name }}</a>
</li>
{%- endfor -%} {% endif %}
</ul>
</div>
</div>
</div>
</footer>
{% endmacro %}

View File

@ -0,0 +1,10 @@
{% macro header(current_section) %}
<header class="navbar">
<div class="container">
<a class="identity" href="{{ config.base_url | safe }}">{{ config.title | default(value="") }}</a>
</div>
{# TODO: Add buttons, perhaps even a menu, to handle navigating to other sections. #}
{# TODO: Add search feature. DO NOT use Zola's #}
{# TODO: Add social networking buttons for Twitter, Github, & Gitea #}
</header>
{% endmacro %}

View File

@ -0,0 +1,3 @@
{% macro stylesheets() %}
<link rel="stylesheet" href="{{ get_url(path="main.css") | safe }}">
{% endmacro %}

50
templates/section.html Normal file
View File

@ -0,0 +1,50 @@
{# Default section.html template #}
{% extends "base.html" %}
{% block seo %}
{{ super() }}
{% set title_addition = "" %}
{% if section.title and config.title %}
{% set title = section.title %}
{% set title_addition = title_separator ~ config.title %}
{% elif section.title %}
{% set title = section.title %}
{% else %}
{% set title = config.title %}
{% endif %}
{% if section.description %}
{% set description = section.description %}
{% else %}
{% set description = config.description %}
{% endif %}
{{ macros_head::seo(title=title, title_addition=title_addition, description=description) }}
{% endblock seo %}
{% block body %}
{% if section.extra.class %}
{% set page_class = section.extra.class %}
{% else %}
{% set page_class = "page list" %}
{% endif %}
{% endblock body %}
{% block content %}
<div class="wrap container" role="document">
<div class="content">
<div class="row justify-content-center">
<div class="col-md-12 col-lg-10 col-xxl-8">
<article>
<div class="page-header">
<h1>{{ section.title }}</h1>
</div>
{{ section.content | safe }}
</article>
</div>
</div>
</div>
</div>
{% endblock content %}