logo logo
Development: Synchronization

Securepub's .sync.py synchronization script makes it easy for developers to work on logically related files under the src/ directory without worrying about where Zola, Elm and esbuild tooling wants them to be kept. It also performs simple conversion and code generation that would typically be done in a makefile.

.sync.py is configured by _sync.conf files in subdirectories of src/.

.sync.py supports four kinds of transformations:

  • File synchronization
  • Merging yaml frontmatter from .md files
  • Converting yaml frontmatter to json for workflows
  • Converting yaml frontmatter to Elm flags

Running .sync.py

.sync.py is typically run by targets in the .justfile.

incremental mode

When run without any arguments .sync.py uses fswatch to detect changes to files under src/. If a file changes the _sync.conf file in the corresponding subdirectory is checked to see if a transformation should be applied.

In the .justfile, the 'dev-sync' target does this for interactive development.

force mode

When run with the --force argument .sync.py instead reads all the _sync.conf files in the immediate children of src/ and applies the corresponding transformation in the same manner it would have in interactive mode had the file changed.

In the .justfile, the 'copy' target does this before a site build.

remove mode

When run with the --remove argument .sync.py removes all the target files it would have written had it been run with --force mode.

In the .justfile, the 'remove' target does this to cleanup build artifacts.


File Synchronization

.sync.py supports copying files from the src/ directory to the work/ directory.

Files listed in the "sync:" section of _sync.conf will be copied to specified locations below the work/ directory.

For example if the _sync.conf in a directory called somedir contains

---
sync:
  foo.md:                       zola/content/_v1.2401_/foo.md
---

Then src/somedir/foo.md will be copied to work/zola/content/_v1.2401_/foo.md:

    src/
      somedir/
        _sync.conf  ╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐
        foo.md ─────────────────┐     ╵
                                │     ╵
    work/                       │     ╵
      zola/                     │  .sync.py
        content/                │
          _v1.2401_/            │
            foo.md ◀────────────┘

Yaml frontmatter merging

.sync.py supports merging to allow multiple .md files to share common yaml data.

The "merge:" section of the _sync.conf identifies files whose frontmatter should be merged into the frontmatter of files listed beneath it before being written to the destination.

For example if we have

---
merge:

  zola/_profile.yaml:
    zola/add.md:                zola/content/_v1.2401_/profile/
    zola/update.md:             zola/content/_v1.2401_/profile/
---

Then the frontmatter of zola/_profile.yaml will be both

  • merged into the frontmatter of zola/add.md and
    the result written to zola/content/_v1.2401_/profile/add.md

  • merged into the frontmatter of zola/update.md and
    the result written to zola/content/_v1.2401_/profile/update.md

as shown below

    src/
      10.profile/
        _sync.conf  ╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐
        zola/                            ╵
                            _profile.md  ╵     _profile.md
                             + add.md    ╵     + update.md
                                │        ╵         │
    work/                       │        ╵         │
      zola/                     │     .sync.py     │
        content/                │                  │
          _v1.2401_/            │                  │
            profile/            │                  │
              add.md ◀──────────┘                  │
              update.md ◀──────────────────────────┘

Converting yaml to json

.sync.py supports converting .yaml files to .json files.

The "tojson:" section of the _sync.conf identifies files which should be parsed as yaml and written to the destination as json with the file extensions changed to .json.

For example the _sync.conf of src/31.topic/_sync.conf contains

---
tojson:

  workflow/load_page.yaml:      zola/static/_v1.2401_/workflow/topic/
---

so that src/31.topic/workflow/load_page.yaml
is converted to work/zola/static/_v1.2401_/workflow/topic/load_page.json

    src/
      31.topic/
        _sync.conf ╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐
        workflow/                      ╵
          load_page.yaml ─────────┐    ╵
                                  │    ╵
    work/                         │    ╵
      zola/                       │ .sync.py
        static/                   │
          _v1.2401_/              │
            workflow/             │
              topic/              │
                load_page.json ◀──┘

Converting yaml to Elm flags

.sync.py supports converting yaml to json and generating Elm flags from the result.

The "toelmflags:" section of the _sync.conf identifies files containing frontmatter which should be parsed as yaml, written as json and the result passed to Securepub's version of the json-to-elm ↗︎ code generator.

For example the _sync.conf of src/31.topic/_sync.conf contains

---
toelmflags:

  zola/_topic.yaml:             elm/src/Topic/Flags.elm
---

so that

  • the frontmatter of src/31.topic/zola/_topic.yaml is parsed as yaml
  • the result written to work/elm/src/Topic/Flags.json and
  • the result of json-to-elm ↗︎ written to work/elm/src/Topic/Flags.elm
    src/
      31.topic/
        _sync.conf ╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐
        zola/                        ╵
          _topic.yaml ──────────┐    ╵
                                │    ╵
    work/                       │    ╵
      elm/                      │ .sync.py
        src/                    │
          Topic/                │
            Flags.json ◀────────┘
               │
               │
               │ json-to-elm
               │
               ▼
            Flags.elm

A complete example

The _sync.conf of src/60.join/_sync.conf shows all the features working together:

---
tojson:

  workflow/login_with_link.yaml:  zola/static/_v1.2401_/workflow/join/

toelmflags:

  zola/_index.md:                 elm/src/Join/Flags.elm

sync:

  elm/Join.elm:                   elm/src/
  elm/Join/Decode.elm:            elm/src/Join/
  elm/Join/Model.elm:             elm/src/Join/
  elm/Join/Valid.elm:             elm/src/Join/
  elm/Join/View.elm:              elm/src/Join/

  ts/main.ts:                     main/join/
  ts/io.ts:                       main/join/

  zola/_index.md:                 zola/content/_v1.2401_/join/
  zola/_index.sp.md:              zola/content/_v1.2401_/join/
---

This configuration

  • generates login_with_link.json from login_with_link.yaml
  • generates Flags.elm from _index.md
  • copies files to work/elm, work/main and work/zola

as shown below

src                               work
└─60.join                         │
  ├─ _sync.conf                   ├─ elm
  ├─ elm                          │  └─ src
  │  ├── Join.elm ╶╶╶╶╶╶╶╶╶sync╶╶╶╶╶╶╶▶ ├─ Join.elm
  │  └── Join                     │     └─ Join
  │      ├── Decode.elm           │        ├─ Decode.elm
  │      │               ╭╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶▶ ├─ Flags.elm
  │      │               ├╶toelmflags╶╶╶╶▶ ├─ Flags.json
  │      ├── Model.elm   ╵        │        ├─ Model.elm
  │      ├── Valid.elm   ╵        │        ├─ Valid.elm
  │      └── View.elm    ╵        │        └─ View.elm
  │                      ╵        │
  │                      ╵        │   
  │                      ╵        ├─ zola
  │                      ╵        │  ├─ content
  │                      ╵        │  │  └─ _v1.2401_
  ├─ zola                ╵        │  │     └─ join
  │  ├── _index.md  ╶╶╶╶╶┴╶sync╶╶╶╶╶╶╶╶╶╶╶╶╶▶ ├─ _index.md
  │  └── _index.sp.md             │  │        └─ _index.sp.md
  │                               │  │
  │                               │  │         
  │                               │  └─ static
  │                               │     └─ _v1.2401_
  │                               │        └─ workflow
  ├─ workflow                     │            └─ join
  │  └── login_with_link.yaml ╶╶╶╶╶╶╶╶tojson╶╶╶╶╶▶ └─ login_with_link.json
  │                               │
  │                               └─ main
  └─ ts                              └─ join
     ├── io.ts  ╶╶╶╶╶╶╶╶╶╶╶sync╶╶╶╶╶╶╶▶ ├─ io.ts
     └── main.ts                        └─ main.ts