Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0b01b92
claude: add Zola migration plan
adrhill Aug 13, 2026
cf30c34
Add Julia preprocessor for the Zola migration (PLAN.md Commit 1)
adrhill Aug 13, 2026
6fcb2b5
Add the Zola scaffold (PLAN.md Commit 2)
adrhill Aug 13, 2026
85e8c99
Migrate content to src/ (PLAN.md Commit 3)
adrhill Aug 13, 2026
9e0acd8
Update toolchain to Julia 1.12, drop --startup-file=no
adrhill Aug 13, 2026
5b716f3
Switch CI to the Zola pipeline (PLAN.md Commit 4)
adrhill Aug 13, 2026
9a3bca5
Fix known-broken external links, trim the checker whitelist
adrhill Aug 13, 2026
23c7385
Replace the Makefile with app subcommands, add a serve watch mode
adrhill Aug 13, 2026
94b3932
Delete the dead Franklin machinery (PLAN.md Commit 5, deletions)
adrhill Aug 13, 2026
e8e3842
Deploy via the GitHub Pages artifact flow instead of the gh-pages branch
adrhill Aug 13, 2026
7550ce6
fix: minor tweaks and fixes
adrhill Aug 14, 2026
1f26f8c
fix: minor syntax highlighting fixes
adrhill Aug 14, 2026
9040b71
fix: parallelization code block tags
adrhill Aug 14, 2026
306bfc7
Restore the in-content TOC via a marker and Tera 2 component
adrhill Aug 14, 2026
3fbfbe7
Update README and CONTRIBUTING for the Zola workflow
adrhill Aug 14, 2026
98df514
chore: rename to `MoJuWoPreprocessor`
adrhill Aug 14, 2026
20ed459
feat: add precommit hooks, Runic formatting
adrhill Aug 14, 2026
90d1596
chore(claude): delete PLAN
adrhill Aug 14, 2026
f8bf13a
chore: delete dead code
adrhill Aug 14, 2026
8fbf8bd
feat: add site search
adrhill Aug 14, 2026
150ceda
fix: bring back CSS for shields.io badge
adrhill Aug 14, 2026
3d78d8b
feat: default to strict mode, failing preprocessor on errors
adrhill Aug 14, 2026
3559640
fix: uncovered error in Aqua code block
adrhill Aug 14, 2026
056d075
feat: switch full-text search to Pagefind
adrhill Aug 15, 2026
1e5b605
ci: only warn on broken external links
adrhill Aug 15, 2026
1af9d78
fix: slightly more verbose CLI output
adrhill Aug 15, 2026
33706d6
feat: fail the build on error-level logs in fences
adrhill Aug 15, 2026
3d76626
feat: isolate page execution in persistent per-page Malt workers
adrhill Aug 15, 2026
dda54ca
fix: give the generated demo package the Test compat Aqua demands
adrhill Aug 15, 2026
8f9bc4a
feat: preprocess pages concurrently
adrhill Aug 15, 2026
9504f83
feat: name the worker pid in the per-page progress log
adrhill Aug 15, 2026
370843c
fix: hide cleanup block
adrhill Aug 15, 2026
8b0d05e
fix(ci): add placeholder git config for PkgTemplates
adrhill Aug 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
79 changes: 72 additions & 7 deletions .github/workflows/Deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,84 @@ on:
branches:
- main
pull_request:

# One run per branch: superseded PR runs are cancelled, while pushes to main
# queue behind the run in progress, so close-together commits can never cancel
# or interleave with a deploy mid-run.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
docs:
build:
runs-on: ubuntu-latest
permissions: write-all
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
# The committed MoJuWoPreprocessor Manifest is resolved for 1.12.
version: '1.12'
- uses: julia-actions/cache@v2
- name: Instantiate the preprocessor
run: julia --project=MoJuWoPreprocessor -e 'using Pkg; Pkg.instantiate()'
- name: Set git user config
# PkgTemplates reads user.name/user.email from the global git config
# when the sharing page generates its demo package.
run: |
git config --global user.name "myusername"
git config --global user.email "myusername@modernjuliaworkflows.github"
- name: 🚀 Build and Deploy
uses: tlienart/xranklin-build-action@main
- name: Execute src/ into content/
# Section envs (src/*/Project.toml) are instantiated per page by the
# preprocessor itself; their Manifests are not committed.
run: julia --project=MoJuWoPreprocessor -m MoJuWoPreprocessor preprocess src content
- name: Install Zola
uses: taiki-e/install-action@v2
with:
tool: zola@0.23.3
- name: Build the site
run: zola build
- name: Index the site for search
# Builds the Pagefind bundle (public/pagefind/) that js/search.js
# loads for the full-text result tier. Runners ship Node for npx.
run: npx -y pagefind@1.5.2 --site public
- name: Check links
# Broken internal links fail the build.
# Broken external links only warn (external_level = "warn" in zola.toml's [link_checker]),
# since CI cannot reliably reach every site.
env:
# Zola swallows link-checker warnings at its default log level.
RUST_LOG: info
run: |
set -o pipefail
zola check 2>&1 | tee zola-check.log
if grep -q "broken external link" zola-check.log; then
{
echo '### :warning: Broken external links'
echo '```'
grep -E 'broken external link|^ *[0-9]+\. Broken link' zola-check.log
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
echo "::warning title=Broken external links::zola check found broken external links — see the job summary for the list."
fi
- name: Upload Pages artifact
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: actions/upload-pages-artifact@v3
with:
DEPLOY: ${{ github.event_name == 'push' }}
DEPLOY_BRANCH: 'gh-pages'
JULIA_VERSION: '1.11'
path: ./public

deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
11 changes: 6 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
__cache/
__site/
content/
_workdir/
public/
.DS_Store
node_modules/
package-lock.json
.vscode
writing/Manifest.toml
sharing/Manifest.toml
optimizing/Manifest.toml
src/writing/Manifest.toml
src/sharing/Manifest.toml
src/optimizing/Manifest.toml
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Vendored third-party code
exclude: ^static/libs/

repos:
- repo: https://github.com/crate-ci/typos
rev: v1.48.0
hooks:
- id: typos
priority: 0
# Use empty args to avoid overwriting false positives.
# Instead, simply fail hook.
args: []

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-merge-conflict
- id: check-added-large-files
- id: check-toml
- id: check-yaml

- repo: https://github.com/fredrikekre/runic-pre-commit
rev: v1.0.0
hooks:
- id: runic

fail_fast: true
72 changes: 70 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,33 @@
If you want to contribute to the blog, start by filing an issue to discuss potential additions.
Then, you can open a pull request.

We suggest you read the [Franklin documentation](https://franklinjl.org/) first to get familiar with the variant of Markdown syntax used here.
The pages under `src/` are written in Markdown with executable code blocks, documented below.

## Building the site locally

MoJuWo is built using Julia 1.12 and [Zola](https://www.getzola.org/documentation/getting-started/installation/) `v0.23`.

Install the preprocessor's dependencies once:

```bash
julia --project=MoJuWoPreprocessor -e 'using Pkg; Pkg.instantiate()'
```

Then, from the repository root:

```bash
julia --project=MoJuWoPreprocessor -m MoJuWoPreprocessor serve
```

The site is built in two steps:

1. a Julia preprocessor ([MoJuWoPreprocessor](MoJuWoPreprocessor/README.md)) executes the code blocks in the authored pages under `src/` and writes the results to the gitignored `content/` directory;
2. [Zola](https://www.getzola.org) renders `content/` into the static site.

This executes every page (the first pass will take some time),
serves the site, and watches `src/`:
saving a page re-runs just that page and live-reloads the browser.
See [MoJuWoPreprocessor/README.md](MoJuWoPreprocessor/README.md) for the remaining commands (e.g., `preprocess`, `build`, `check`, `clean`).

## Style guide

Expand All @@ -20,4 +46,46 @@ Every time a new resource is introduced, it should be accompanied with a link to
Links to the package documentation are not necessary, unless they are meant to highlight a specific part.

Package names are written as normal text with the .jl extension, while functions or objects are written between backticks.
Multi-line scripts are given as Julia code or REPL blocks following the Franklin specification.
Multi-line scripts are given as executable code blocks, so that readers always see real, up-to-date output.

## Executable code blocks

Julia code blocks are executed when the site is built, and their output is rendered below the code like a REPL session.
The first character of the fence's info string selects the REPL mode, and the rest names the block:

```>example
x = 1
x + 1
```

- ` ```>name ` — julia mode: expressions are echoed and evaluated one by one, like in the REPL;
- ` ```?name ` — help mode;
- ` ```]name ` — pkg mode;
- ` ```;name ` — shell mode;
- ` ```!name ` — script mode: the code runs silently and is shown as a plain ` ```julia ` block, followed by its printed output. A `# hideall` comment hides the whole block, and a trailing `# hide` hides a single line.

A code block whose error is part of the lesson must be marked with an ` allow-error` flag, e.g. ` ```>name allow-error `: the error message then renders like any other REPL output.
Without the flag, an erroring code block fails the site build, as does any unclosed fence.

All named fences on a page share one sandbox module, so later blocks can use variables defined in earlier ones.
Two conventions replace explicit setup code:

- If the page's directory contains a `Project.toml`, that environment is activated while the page runs. Add the packages your code blocks need there.
- Code blocks run inside a per-page scratch directory, so files are created and read with plain relative paths, exactly as a reader would type them.

## Admonitions

Callout boxes use the components defined in [`templates/components.html`](templates/components.html): `tldr`, `advanced`, and `vscode`.
The body is regular Markdown:

```markdown
{% <tldr> %}
A quick summary of the section.
{% </tldr> %}
```

Everything else is standard [Zola](https://www.getzola.org/documentation/):
the layout lives in `templates/`,
written as [Tera templates](https://www.getzola.org/documentation/templates/overview/),
styles live in `static/css/`,
and the site configuration in `zola.toml`.
Loading
Loading