From 1d55f70fad210b4ef0cedad5844e54756e1531d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Tue, 27 Oct 2026 00:52:30 +0100 Subject: [PATCH 1/3] Fix the anchor of the links to the ghcr.io section --- doc/configuration.md | 2 +- doc/tasks.md | 2 +- tools/{mkdocs => doc}/.gitignore | 0 tools/{mkdocs => doc}/Dockerfile | 0 .../{mkdocs => doc}/cards-layouts/custom.yml | 0 tools/{mkdocs => doc}/castor.php | 0 tools/{mkdocs => doc}/overrides/404.html | 0 tools/{mkdocs => doc}/overrides/main.html | 0 .../overrides/partials/header.html | 0 tools/mkdocs/mkdocs.yml | 107 ------------------ 10 files changed, 2 insertions(+), 109 deletions(-) rename tools/{mkdocs => doc}/.gitignore (100%) rename tools/{mkdocs => doc}/Dockerfile (100%) rename tools/{mkdocs => doc}/cards-layouts/custom.yml (100%) rename tools/{mkdocs => doc}/castor.php (100%) rename tools/{mkdocs => doc}/overrides/404.html (100%) rename tools/{mkdocs => doc}/overrides/main.html (100%) rename tools/{mkdocs => doc}/overrides/partials/header.html (100%) delete mode 100644 tools/mkdocs/mkdocs.yml diff --git a/doc/configuration.md b/doc/configuration.md index 18abe46..8a57add 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -25,7 +25,7 @@ function default_context(): Context |----------|------| | `root_domain` | Root domain used by the services exposing a UI (`redis.{root_domain}`, `mailpit.{root_domain}`, …) | | `registry` | Registry the build cache is pushed to and pulled from | -| `repository` | Repository `castor docker:push` labels the images with, so the registry attaches the packages to it — deduced from `GITHUB_REPOSITORY` or the `origin` remote otherwise, see [`docker:push`](tasks.md#publishing-to-ghcr-io) | +| `repository` | Repository `castor docker:push` labels the images with, so the registry attaches the packages to it — deduced from `GITHUB_REPOSITORY` or the `origin` remote otherwise, see [`docker:push`](tasks.md#publishing-to-ghcrio) | | `project_name` | Compose project name — wins over the `name:` of `compose.yaml`, see [running two checkouts side by side](#running-two-checkouts-side-by-side) | | `user_id` | UID the containers run as, defaults to your own | | `twig_dockerfile_frontend` | Overrides the pinned [twig-dockerfile frontend](going-further/custom-dockerfile.md#pinning-the-frontend) | diff --git a/doc/tasks.md b/doc/tasks.md index a2c7ba4..584653a 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -265,7 +265,7 @@ and its image under `latest` — `--tag` publishes it under another name. A service listing several caches in its `cache_from` pushes to all of them, and its image to each registry among them. The image carries `org.opencontainers.image.source`, which is what -[attaches the package to your repository](#publishing-to-ghcr-io). +[attaches the package to your repository](#publishing-to-ghcrio). `--dry-run` prints the build plan bake resolved, without running it. diff --git a/tools/mkdocs/.gitignore b/tools/doc/.gitignore similarity index 100% rename from tools/mkdocs/.gitignore rename to tools/doc/.gitignore diff --git a/tools/mkdocs/Dockerfile b/tools/doc/Dockerfile similarity index 100% rename from tools/mkdocs/Dockerfile rename to tools/doc/Dockerfile diff --git a/tools/mkdocs/cards-layouts/custom.yml b/tools/doc/cards-layouts/custom.yml similarity index 100% rename from tools/mkdocs/cards-layouts/custom.yml rename to tools/doc/cards-layouts/custom.yml diff --git a/tools/mkdocs/castor.php b/tools/doc/castor.php similarity index 100% rename from tools/mkdocs/castor.php rename to tools/doc/castor.php diff --git a/tools/mkdocs/overrides/404.html b/tools/doc/overrides/404.html similarity index 100% rename from tools/mkdocs/overrides/404.html rename to tools/doc/overrides/404.html diff --git a/tools/mkdocs/overrides/main.html b/tools/doc/overrides/main.html similarity index 100% rename from tools/mkdocs/overrides/main.html rename to tools/doc/overrides/main.html diff --git a/tools/mkdocs/overrides/partials/header.html b/tools/doc/overrides/partials/header.html similarity index 100% rename from tools/mkdocs/overrides/partials/header.html rename to tools/doc/overrides/partials/header.html diff --git a/tools/mkdocs/mkdocs.yml b/tools/mkdocs/mkdocs.yml deleted file mode 100644 index 0852c93..0000000 --- a/tools/mkdocs/mkdocs.yml +++ /dev/null @@ -1,107 +0,0 @@ -site_name: Castor Docker - Docker environments for PHP -site_description: A Castor plugin that generates your Docker Compose stack and the tasks to drive it, for PHP applications and everything around them. -site_url: https://castor-php.github.io/docker/ -repo_url: https://github.com/castor-php/docker - -edit_uri: edit/main/doc/ -docs_dir: doc -exclude_docs: | - _nav.md - -theme: - name: material - logo: assets/logo_CASTOR_line.svg - favicon: assets/favicon.png - icon: - repo: fontawesome/brands/github - language: en - palette: - # Palette toggle for automatic mode - - media: "(prefers-color-scheme)" - scheme: default - primary: white - accent: amber - toggle: - icon: material/brightness-auto - name: Switch to light mode - - # Palette toggle for light mode - - media: "(prefers-color-scheme: light)" - scheme: default - primary: white - accent: amber - toggle: - icon: material/brightness-7 - name: Switch to dark mode - - # Palette toggle for dark mode - - media: "(prefers-color-scheme: dark)" - scheme: slate - primary: black - accent: amber - toggle: - icon: material/brightness-4 - name: Switch to system preference - features: - - content.action.edit - - content.code.copy - - content.tabs.link - - navigation.footer - - navigation.indexes - - navigation.instant - - navigation.instant.prefetch - - navigation.path - - navigation.sections - - navigation.tabs - - navigation.tabs.sticky - - navigation.top - - navigation.tracking - - search.highlight - - toc.integrate - custom_dir: overrides - -extra: - social: - - icon: fontawesome/brands/github-alt - link: https://github.com/castor-php - - icon: fontawesome/brands/x-twitter - link: https://x.com/jolicode - generator: false - -markdown_extensions: - - admonition - - attr_list - - github-callouts - - footnotes - - pymdownx.details - - pymdownx.highlight: - use_pygments: false - - pymdownx.inlinehilite - - pymdownx.snippets - - pymdownx.superfences - - pymdownx.tabbed: - alternate_style: true - combine_header_slug: true - slugify: !!python/object/apply:pymdownx.slugs.slugify - kwds: - case: lower - - toc: - permalink: true - -plugins: - - search - - literate-nav: - nav_file: _nav.md - - include-markdown - - social: - cards_layout_dir: cards-layouts - cards_layout: custom - cards_layout_options: - font_family: Noto Sans SC - background_color: white - -extra_javascript: - - assets/javascripts/highlight.min.js -extra_css: - - assets/stylesheets/highlight-github.min.css - - assets/stylesheets/jolicode.css From 517d4c6dd37614528792d27ac2d55c73c5ef518d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Tue, 27 Oct 2026 00:52:31 +0100 Subject: [PATCH 2/3] Migrate the documentation from MkDocs to Zensical --- .github/workflows/documentation.yml | 6 +- README.md | 4 +- castor.php | 2 +- doc/changelog.md | 3 +- doc/index.md | 3 +- tools/doc/.gitignore | 2 + tools/doc/Dockerfile | 23 +---- tools/doc/cards-layouts/custom.yml | 2 +- tools/doc/castor.php | 33 ++++--- tools/doc/main.py | 27 ++++++ tools/doc/overrides/main.html | 2 +- tools/doc/overrides/partials/header.html | 106 +++++++++++----------- tools/doc/zensical.toml | 111 +++++++++++++++++++++++ 13 files changed, 225 insertions(+), 99 deletions(-) create mode 100644 tools/doc/main.py create mode 100644 tools/doc/zensical.toml diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 41d610e..92c51d2 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -19,7 +19,7 @@ permissions: {} jobs: build: - name: Build documentation website with MkDocs + name: Build documentation website with Zensical runs-on: ubuntu-latest permissions: contents: read @@ -40,13 +40,13 @@ jobs: # Turn Pages on if it is not already, instead of failing enablement: true - - name: Build site with mkdocs + - name: Build the documentation website run: castor docs:build - name: Upload artifact uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 with: - path: ./tools/mkdocs/site + path: ./tools/doc/site deploy: name: Deploy to GitHub Pages diff --git a/README.md b/README.md index f57c5a4..0e142b4 100644 --- a/README.md +++ b/README.md @@ -142,11 +142,11 @@ multiple applications and services. ## Contributing -The documentation lives in [`doc/`](./doc/) and is built with MkDocs: +The documentation lives in [`doc/`](./doc/) and is built with [Zensical](https://zensical.org/): ```bash castor docs:serve # http://127.0.0.1:8000, rebuilds on change -castor docs:build # build the static site in tools/mkdocs/site +castor docs:build # build the static site in tools/doc/site ``` Quality tooling for the plugin itself: diff --git a/castor.php b/castor.php index 2f7f0a9..a4c23a0 100644 --- a/castor.php +++ b/castor.php @@ -11,7 +11,7 @@ defined('CASTOR_USE_CHDIR') || define('CASTOR_USE_CHDIR', false); -import(__DIR__ . '/tools/mkdocs/castor.php'); +import(__DIR__ . '/tools/doc/castor.php'); #[AsTask(description: 'Run PHPStan', namespace: 'qa', name: 'phpstan', aliases: ['phpstan'])] function qa_phpstan(bool $generateBaseline = false): int diff --git a/doc/changelog.md b/doc/changelog.md index 0e4a63b..3a403a6 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,8 +1,9 @@ --- +render_macros: true title: Changelog description: What changed in each release of the Castor Docker plugin. --- -{% include-markdown "../CHANGELOG.md" %} +{{ markdown("CHANGELOG.md") }} diff --git a/doc/index.md b/doc/index.md index bed0f59..07af155 100644 --- a/doc/index.md +++ b/doc/index.md @@ -1,4 +1,5 @@ --- +render_macros: true title: Docker environments for PHP, driven from PHP description: A Castor plugin that generates your Docker Compose stack and the tasks to drive it — applications, databases, router and HTTPS included. --- @@ -17,7 +18,7 @@ description: A Castor plugin that generates your Docker Compose stack and the ta ## 🚀 TL;DR -{% include-markdown "../README.md" start="" end="" %} +{{ markdown("README.md", start="", end="") }} ## Want more? diff --git a/tools/doc/.gitignore b/tools/doc/.gitignore index 4809185..18d7a9c 100644 --- a/tools/doc/.gitignore +++ b/tools/doc/.gitignore @@ -5,3 +5,5 @@ doc/ example/ site/ overrides/partials/jolicode-footer.html +__pycache__/ +__pycache__/ diff --git a/tools/doc/Dockerfile b/tools/doc/Dockerfile index d2c5fb1..c52a768 100644 --- a/tools/doc/Dockerfile +++ b/tools/doc/Dockerfile @@ -1,24 +1,9 @@ FROM python:3-slim -WORKDIR /mkdocs/ +WORKDIR /doc/ RUN pip install \ - mkdocs\ - mkdocs-material\ - mkdocs-material[imaging]\ - markdown-callouts\ - mkdocs-literate-nav\ - mkdocs-include-markdown-plugin + zensical \ + markdown-callouts -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - libcairo2-dev \ - libfreetype6-dev \ - libffi-dev \ - libjpeg-dev \ - libpng-dev \ - libz-dev \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* \ - -CMD ["mkdocs", "serve"] +CMD ["zensical", "serve"] diff --git a/tools/doc/cards-layouts/custom.yml b/tools/doc/cards-layouts/custom.yml index 9ab24c8..73da07a 100644 --- a/tools/doc/cards-layouts/custom.yml +++ b/tools/doc/cards-layouts/custom.yml @@ -6,7 +6,7 @@ layers: - size: { width: 385, height: 100 } offset: { x: 50, y: 50 } background: - image: /mkdocs/doc/assets/logo_CASTOR_line@2x.png + image: /doc/doc/assets/logo_CASTOR_line@2x.png - size: { width: 1200, height: 10 } offset: { x: 0, y: 620 } diff --git a/tools/doc/castor.php b/tools/doc/castor.php index 0064357..dcd138f 100644 --- a/tools/doc/castor.php +++ b/tools/doc/castor.php @@ -13,9 +13,9 @@ use function Castor\io; use function Castor\run; -const IMAGE_NAME = 'castor-docker-mkdocs'; +const IMAGE_NAME = 'castor-docker-doc'; -#[AsTask(description: 'Build the MkDocs Docker image', namespace: 'docs', name: 'image')] +#[AsTask(description: 'Build the documentation Docker image', namespace: 'docs', name: 'image')] function image(bool $force = false): void { if (!$force && has_image()) { @@ -24,7 +24,7 @@ function image(bool $force = false): void return; } - io()->title('Building the MkDocs Docker image'); + io()->title('Building the documentation Docker image'); run(['docker', 'build', '-t', IMAGE_NAME, __DIR__]); } @@ -32,10 +32,10 @@ function image(bool $force = false): void #[AsTask(description: 'Fetch the JoliCode theme assets used by the documentation', namespace: 'docs', name: 'assets')] function assets(): void { - io()->title('Fetching external assets for the MkDocs documentation'); + io()->title('Fetching external assets for the documentation'); http_download( - 'https://raw.githubusercontent.com/jolicode/oss-theme/refs/heads/main/MkDocs/extra.css', + 'https://raw.githubusercontent.com/jolicode/oss-theme/refs/heads/main/Zensical/extra.css', root() . '/doc/assets/stylesheets/jolicode.css', ); http_download( @@ -64,9 +64,9 @@ function build(): void { assets(); - io()->title('Building the MkDocs documentation'); + io()->title('Building the documentation'); - do_run(['mkdocs', 'build']); + do_run(['zensical', 'build', '--strict']); io()->success(\sprintf('Documentation built in %s/site.', __DIR__)); } @@ -76,11 +76,11 @@ function serve(int $port = 8000): void { assets(); - io()->title('Serving the MkDocs documentation'); + io()->title('Serving the documentation'); io()->writeln(\sprintf(' http://127.0.0.1:%d', $port)); do_run( - ['mkdocs', 'serve', '--livereload', '--dev-addr', '0.0.0.0:8000'], + ['zensical', 'serve', '--dev-addr', '0.0.0.0:8000'], ports: [\sprintf('%d:8000', $port)], ); } @@ -117,16 +117,15 @@ function do_run(array $command, array $ports = []): Process $arguments = [ 'docker', 'run', '--rm', '--init', '--user', "{$userId}:{$groupId}", - // The image installs MkDocs system-wide, but the social plugin wants a - // writable home for its font cache. + // The social plugin wants a writable home for its font cache. '--env', 'HOME=/tmp', - '--volume', \sprintf('%s:/mkdocs:cached', __DIR__), + '--volume', \sprintf('%s:/doc:cached', __DIR__), // Mounted next to the docs so pages can include them, see the - // "include-markdown" directives in doc/. - '--volume', \sprintf('%s:/mkdocs/doc:cached', root() . '/doc'), - '--volume', \sprintf('%s:/mkdocs/README.md:cached', root() . '/README.md'), - '--volume', \sprintf('%s:/mkdocs/CHANGELOG.md:cached', root() . '/CHANGELOG.md'), - '--volume', \sprintf('%s:/mkdocs/example:cached', root() . '/example'), + // markdown() macros in doc/. + '--volume', \sprintf('%s:/doc/doc:cached', root() . '/doc'), + '--volume', \sprintf('%s:/doc/README.md:cached', root() . '/README.md'), + '--volume', \sprintf('%s:/doc/CHANGELOG.md:cached', root() . '/CHANGELOG.md'), + '--volume', \sprintf('%s:/doc/example:cached', root() . '/example'), ]; foreach ($ports as $port) { diff --git a/tools/doc/main.py b/tools/doc/main.py new file mode 100644 index 0000000..fa30c77 --- /dev/null +++ b/tools/doc/main.py @@ -0,0 +1,27 @@ +"""Macros used by the documentation, see https://zensical.org/docs/compatibility/mkdocs/plugins/#macros""" + +import os + +ROOT = os.path.dirname(os.path.abspath(__file__)) + + +def define_env(env): + @env.macro + def markdown(path, start=None, end=None): + """Include a Markdown file, or only the part between the start and end markers.""" + file = os.path.join(ROOT, path) + if not os.path.isfile(file): + raise FileNotFoundError(f'The file "{path}" included in "{env.page.path}" does not exist.') + + with open(file) as f: + content = f.read() + + for marker in (start, end): + if marker and marker not in content: + raise ValueError(f'The marker "{marker}" was not found in "{path}", included in "{env.page.path}".') + if start: + content = content.split(start, 1)[1] + if end: + content = content.split(end, 1)[0] + + return content diff --git a/tools/doc/overrides/main.html b/tools/doc/overrides/main.html index 793db39..fd7428d 100644 --- a/tools/doc/overrides/main.html +++ b/tools/doc/overrides/main.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block htmltitle %} - {% if page.is_homepage %} + {% if page.meta and page.meta.title and not page.url %} {{ page.meta.title }} {% elif page.meta and page.meta.title %} {{ page.meta.title }} - Castor Docker plugin diff --git a/tools/doc/overrides/partials/header.html b/tools/doc/overrides/partials/header.html index 690f27f..0510026 100644 --- a/tools/doc/overrides/partials/header.html +++ b/tools/doc/overrides/partials/header.html @@ -1,68 +1,68 @@ -{# Retrieved from https://github.com/squidfunk/mkdocs-material/blob/master/src/templates/partials/header.html to override site name #} +{# Retrieved from zensical/templates/partials/header.html to override site name #} {% set class = "md-header" %} {% if "navigation.tabs.sticky" in features %} - {% set class = class ~ " md-header--shadow md-header--lifted" %} - {% elif "navigation.tabs" not in features %} - {% set class = class ~ " md-header--shadow" %} + {% set class = class ~ " md-header--shadow md-header--lifted" %} +{% elif "navigation.tabs" not in features %} + {% set class = class ~ " md-header--shadow" %} {% endif %}
- + {% if "navigation.tabs.sticky" in features %} + {% if "navigation.tabs" in features %} + {% include "partials/tabs.html" %} {% endif %} + {% endif %}
diff --git a/tools/doc/zensical.toml b/tools/doc/zensical.toml new file mode 100644 index 0000000..011bbe4 --- /dev/null +++ b/tools/doc/zensical.toml @@ -0,0 +1,111 @@ +[project] +site_name = "Castor Docker - Docker environments for PHP" +site_description = "A Castor plugin that generates your Docker Compose stack and the tasks to drive it, for PHP applications and everything around them." +site_url = "https://castor-php.github.io/docker/" +repo_url = "https://github.com/castor-php/docker" +edit_uri = "edit/main/doc/" +docs_dir = "doc" +exclude_docs = "_nav.md" +extra_javascript = [ + "assets/javascripts/highlight.min.js", +] +extra_css = [ + "assets/stylesheets/highlight-github.min.css", + "assets/stylesheets/jolicode.css", +] + +[project.theme] +logo = "assets/logo_CASTOR_line.svg" +favicon = "assets/favicon.png" +language = "en" +custom_dir = "overrides" +features = [ + "content.action.edit", + "content.code.copy", + "content.tabs.link", + "navigation.footer", + "navigation.indexes", + "navigation.instant", + "navigation.instant.prefetch", + "navigation.path", + "navigation.sections", + "navigation.tabs", + "navigation.tabs.sticky", + "navigation.top", + "navigation.tracking", + "search.highlight", + "toc.integrate", +] + +[project.theme.icon] +repo = "fontawesome/brands/github" + +# Palette toggle for automatic mode +[[project.theme.palette]] +media = "(prefers-color-scheme)" +scheme = "default" +primary = "white" +accent = "amber" +toggle.icon = "material/brightness-auto" +toggle.name = "Switch to light mode" + +# Palette toggle for light mode +[[project.theme.palette]] +media = "(prefers-color-scheme: light)" +scheme = "default" +primary = "white" +accent = "amber" +toggle.icon = "material/brightness-7" +toggle.name = "Switch to dark mode" + +# Palette toggle for dark mode +[[project.theme.palette]] +media = "(prefers-color-scheme: dark)" +scheme = "slate" +primary = "black" +accent = "amber" +toggle.icon = "material/brightness-4" +toggle.name = "Switch to system preference" + +[project.extra] +generator = false + +[[project.extra.social]] +icon = "fontawesome/brands/github-alt" +link = "https://github.com/castor-php" + +[[project.extra.social]] +icon = "fontawesome/brands/x-twitter" +link = "https://x.com/jolicode" + +[project.markdown_extensions] +admonition = {} +attr_list = {} +"github-callouts" = {} +footnotes = {} +pymdownx.details = {} +pymdownx.highlight.use_pygments = false +pymdownx.inlinehilite = {} +pymdownx.snippets = {} +pymdownx.superfences = {} +pymdownx.tabbed.alternate_style = true +pymdownx.tabbed.combine_header_slug = true +pymdownx.tabbed.slugify.object = "pymdownx.slugs.slugify" +pymdownx.tabbed.slugify.kwds.case = "lower" +toc.permalink = true + +[project.plugins.search] + +[project.plugins."literate-nav"] +nav_file = "_nav.md" + +# The pages opt in with "render_macros: true": most of them show Twig syntax that must stay as is. +[project.plugins.macros] +render_by_default = false +on_error_fail = true + +[project.plugins.social] +cards_layout_dir = "cards-layouts" +cards_layout = "custom" +cards_layout_options.font_family = "Noto Sans SC" +cards_layout_options.background_color = "white" From d1831ac49b85f97846f508c63ff1d00fe49c18a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Tue, 27 Oct 2026 00:52:31 +0100 Subject: [PATCH 3/3] Check the documentation build in the CI --- .github/workflows/ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18c6220..4c7d78d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,21 @@ jobs: - name: PHP CS Fixer run: castor qa:cs --dry-run + docs: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Setup Castor + uses: castor-php/setup-castor@2a495b8c91f00be6768ad8a040ba8634c797d386 # v1.1.0 + + - name: Build the documentation website + run: castor docs:build + zizmor: name: GitHub Actions security analysis runs-on: ubuntu-latest