diff --git a/Documentation/Index.rst b/Documentation/Index.rst index 3917646f5..92fb00131 100644 --- a/Documentation/Index.rst +++ b/Documentation/Index.rst @@ -45,4 +45,5 @@ to extend the tool. Developer/Index Redirects/Index Migration/Index + Templating/Index KnownProblems/Index diff --git a/Documentation/Templating/Index.rst b/Documentation/Templating/Index.rst new file mode 100644 index 000000000..5eec99b68 --- /dev/null +++ b/Documentation/Templating/Index.rst @@ -0,0 +1,237 @@ +.. include:: /Includes.rst.txt + +.. _override-templates: + +==================== +Overriding templates +==================== + +By default, the render-guides container uses the Twig templates shipped +with the official TYPO3 Documentation theme. You can provide your own +templates to customize or extend the rendering output **without modifying +the container image**. + +.. important:: + + Custom templates are only supported when you build the documentation + **locally** (for example using Docker or DDEV) or within your **own + CI/CD pipeline**. + + When your project documentation is built and deployed automatically via + the **official TYPO3 documentation workflow** (to + `https://docs.typo3.org `_), custom templates + are **not supported**. + + The central rendering service uses a fixed, controlled version of the + official theme to ensure consistency across all published manuals. + +.. _template-override-mechanism: + +How template overriding works +============================= + +The TYPO3 Documentation theme registers a list of template search paths. +When rendering, the Twig template engine resolves templates by checking +these paths **in order** and using the first match. + +When custom template directories are present, they are prepended to the +search path, giving them higher priority than the built-in templates. + +The resolution order is: + +#. Custom templates mounted via Docker volume at :file:`/templates` + (highest priority) +#. Custom templates bundled in the project at + :file:`resources/custom-templates` (relative to the project root) +#. TYPO3-specific theme templates +#. Bootstrap 5 theme templates (fallback) +#. Base phpDocumentor templates (fallback) + +.. _template-docker-volume: + +Method 1: mount a Docker volume +=============================== + +Mount a local directory into the container at the path :file:`/templates`. + +For example, if your custom templates are stored in a folder named +:file:`my-custom-templates` in your current working directory: + +.. code-block:: shell + + docker run --rm \ + --pull always \ + -v "$(pwd):/project" \ + -v "$(pwd)/my-custom-templates:/templates:ro" \ + -it ghcr.io/typo3-documentation/render-guides:latest \ + --progress --config=Documentation + +.. note:: + + The :file:`/templates` path is **separate from** the :file:`/project` + mount point. This avoids volume mount ordering issues that can occur + when nesting volumes. + +.. _template-project-bundled: + +Method 2: bundle templates in your project +========================================== + +Place your custom templates in a directory named +:file:`resources/custom-templates` **at the root of your repository**: + +.. code-block:: text + + my-project/ + |-- Documentation/ + | |-- Index.rst + | +-- ... + |-- resources/ + | +-- custom-templates/ + | +-- structure/ + | +-- layout.html.twig + +-- ... + +When you mount your project into the container with +``-v "$(pwd):/project"``, the path +:file:`/project/resources/custom-templates` is detected automatically. +No extra volume mount is needed: + +.. code-block:: shell + + docker run --rm \ + --pull always \ + -v "$(pwd):/project" \ + -it ghcr.io/typo3-documentation/render-guides:latest \ + --progress --config=Documentation + +.. _template-directory-structure: + +Directory structure for custom templates +======================================== + +Your custom templates must mirror the internal directory structure of the +built-in templates you want to override. + +For example, if the original file is located at: + +.. code-block:: text + + typo3-docs-theme/resources/template/structure/layout.html.twig + +then your custom file must be placed at: + +.. code-block:: text + + my-custom-templates/structure/layout.html.twig + +When both files exist, your version is used instead of the original. +Any template you do **not** override continues to use the built-in +version. + +.. _template-finding-originals: + +Finding the original templates +============================== + +To create a customized version of a template, first copy the original +from the container image. + +Open a shell inside the container to browse all available templates: + +.. code-block:: shell + + docker run --rm -it \ + --entrypoint=sh \ + ghcr.io/typo3-documentation/render-guides:latest + +.. note:: + + The ``--entrypoint=sh`` flag is required because the container's + default entrypoint routes all commands to the PHP guides application. + Without it, shell commands like ``cat`` or ``ls`` would be + interpreted as guides subcommands. + +Once inside, the templates are organized as follows: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - **Theme / Purpose** + - **Location in container** + * - TYPO3-specific templates + - :file:`/opt/guides/packages/typo3-docs-theme/resources/template/` + * - Bootstrap 5 theme templates + - :file:`/opt/guides/vendor/phpdocumentor/guides-theme-bootstrap/resources/template/` + * - reStructuredText (reST) templates + - :file:`/opt/guides/vendor/phpdocumentor/guides-restructured-text/resources/template/html/` + * - Base templates (shared core) + - :file:`/opt/guides/vendor/phpdocumentor/guides/resources/template/html/` + +.. _template-copying: + +Copying a template from the container +------------------------------------- + +To copy a specific template to your local machine, use +``--entrypoint=cat``: + +.. code-block:: shell + + docker run --rm \ + --entrypoint=cat \ + ghcr.io/typo3-documentation/render-guides:latest \ + /opt/guides/packages/typo3-docs-theme/resources/template/structure/layout.html.twig \ + > my-custom-templates/structure/layout.html.twig + +Make sure the target directory exists before running the command: + +.. code-block:: shell + + mkdir -p my-custom-templates/structure + +Edit the copied file locally. The next time you run the container with +your custom templates mounted, your modified version will automatically +be used. + +.. _template-examples: + +Examples +======== + +Override the page layout +------------------------ + +.. code-block:: shell + + mkdir -p my-custom-templates/structure + + docker run --rm \ + --entrypoint=cat \ + ghcr.io/typo3-documentation/render-guides:latest \ + /opt/guides/packages/typo3-docs-theme/resources/template/structure/layout.html.twig \ + > my-custom-templates/structure/layout.html.twig + + # Edit my-custom-templates/structure/layout.html.twig to your liking + + docker run --rm \ + -v "$(pwd):/project" \ + -v "$(pwd)/my-custom-templates:/templates:ro" \ + -it ghcr.io/typo3-documentation/render-guides:latest \ + --progress --config=Documentation + +Override block quote rendering +------------------------------ + +.. code-block:: shell + + mkdir -p my-custom-templates/body + + docker run --rm \ + --entrypoint=cat \ + ghcr.io/typo3-documentation/render-guides:latest \ + /opt/guides/vendor/phpdocumentor/guides/resources/template/html/body/quote.html.twig \ + > my-custom-templates/body/quote.html.twig + + # Edit and render as above diff --git a/composer.lock b/composer.lock index caa88f7da..80bc72ad0 100644 --- a/composer.lock +++ b/composer.lock @@ -6206,16 +6206,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.94.0", + "version": "v3.94.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4" + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/883b20fb38c7866de9844ab6d0a205c423bde2d4", - "reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63", + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63", "shasum": "" }, "require": { @@ -6298,7 +6298,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2" }, "funding": [ { @@ -6306,7 +6306,7 @@ "type": "github" } ], - "time": "2026-02-11T16:44:33+00:00" + "time": "2026-02-20T16:13:53+00:00" }, { "name": "justinrainbow/json-schema", diff --git a/packages/typo3-docs-theme/src/DependencyInjection/Typo3DocsThemeExtension.php b/packages/typo3-docs-theme/src/DependencyInjection/Typo3DocsThemeExtension.php index 05984ef7c..5f7c6e5ed 100644 --- a/packages/typo3-docs-theme/src/DependencyInjection/Typo3DocsThemeExtension.php +++ b/packages/typo3-docs-theme/src/DependencyInjection/Typo3DocsThemeExtension.php @@ -97,11 +97,26 @@ private function getConfigValue(array $configs, string $key, string $default): s public function prepend(ContainerBuilder $container): void { + $templates = []; + + // Docker volume mount: highest custom priority + if (is_dir('/templates') && is_readable('/templates')) { + $templates[] = '/templates'; + } + + // Project-bundled templates: second custom priority + if (is_dir('/project/resources/custom-templates') && is_readable('/project/resources/custom-templates')) { + $templates[] = '/project/resources/custom-templates'; + } + + // Built-in theme templates: lowest priority (fallback) + $templates[] = dirname(__DIR__, 2) . '/resources/template'; + $container->prependExtensionConfig('guides', [ 'themes' => [ 'typo3docs' => [ 'extends' => 'bootstrap', - 'templates' => [dirname(__DIR__, 2) . '/resources/template'], + 'templates' => $templates, ], ],