From 68466b681c37adad35c93240eb379424203a8fa0 Mon Sep 17 00:00:00 2001 From: Marek Skopal Date: Fri, 5 Jun 2026 15:51:28 +0200 Subject: [PATCH 1/2] docs: place template-override settings inside preUserFunc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Template-Overrides example, the architecture note in Resources/AGENTS.md, and the inline comment in Configuration/TypoScript/ImageRendering/setup.typoscript all show the template override as: lib.parseFunc_RTE.tags.img { settings.templateRootPaths.10 = EXT:my_sitepackage/... } That placement does not work. ContentObjectRenderer::stdWrap_preUserFunc only forwards $conf['preUserFunc.'] (the sub-array of the preUserFunc key) to the callable — anything placed as a sibling of preUserFunc under tags.img is invisible to ImageRenderingService::buildTemplatePaths(). Move the example under preUserFunc.settings.* and document the same requirement for externalBlocks.figure.stdWrap.preUserFunc (used by renderFigure() for captioned figures). Signed-off-by: Marek Skopal --- .../ImageRendering/setup.typoscript | 15 +++++-- Documentation/Examples/Template-Overrides.rst | 39 ++++++++++++++----- Resources/AGENTS.md | 18 ++++++++- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/Configuration/TypoScript/ImageRendering/setup.typoscript b/Configuration/TypoScript/ImageRendering/setup.typoscript index d43d9b30..e01f5bef 100755 --- a/Configuration/TypoScript/ImageRendering/setup.typoscript +++ b/Configuration/TypoScript/ImageRendering/setup.typoscript @@ -25,18 +25,25 @@ lib.parseFunc_RTE { # IMPORTANT: Use the extension key "rte_ckeditor_image" (underscores) in # EXT: paths, NOT the Composer package name "rte-ckeditor-image" (hyphens). # - # To override, add your paths with priority > 0: + # To override, add your paths with priority > 0 INSIDE preUserFunc.* — + # TYPO3's stdWrap_preUserFunc only forwards $conf['preUserFunc.'] to the + # callable, so a settings.* block placed as a sibling of preUserFunc + # never reaches ImageRenderingService::buildTemplatePaths(). # - # settings.templateRootPaths { + # preUserFunc.settings.templateRootPaths { # 10 = EXT:my_sitepackage/Resources/Private/Templates/ # } - # settings.partialRootPaths { + # preUserFunc.settings.partialRootPaths { # 10 = EXT:my_sitepackage/Resources/Private/Partials/ # } - # settings.layoutRootPaths { + # preUserFunc.settings.layoutRootPaths { # 10 = EXT:my_sitepackage/Resources/Private/Layouts/ # } # + # The same settings.* block must also be added under + # lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc for + # captioned (figure-wrapped) images. + # # See Documentation/Examples/Template-Overrides.rst for details. #****************************************************** diff --git a/Documentation/Examples/Template-Overrides.rst b/Documentation/Examples/Template-Overrides.rst index 8cff11f7..6827c06b 100644 --- a/Documentation/Examples/Template-Overrides.rst +++ b/Documentation/Examples/Template-Overrides.rst @@ -190,12 +190,19 @@ In your site package, create the override directory: Step 2: Configure TypoScript ---------------------------- -Add the template path to your TypoScript setup: +Add the template path to your TypoScript setup. The ``settings.*`` block +must live **inside** ``preUserFunc.`` — that is the only sub-array TYPO3 +forwards to the rendering callable (see +:php:`ContentObjectRenderer::stdWrap_preUserFunc()`, which passes only +``$conf['preUserFunc.']`` to the user function). Placing +``settings.templateRootPaths`` as a sibling of ``preUserFunc`` has no +effect — the configuration never reaches +:php:`ImageRenderingService::buildTemplatePaths()`. .. code-block:: typoscript :caption: EXT:my_sitepackage/Configuration/TypoScript/setup.typoscript - lib.parseFunc_RTE.tags.img { + lib.parseFunc_RTE.tags.img.preUserFunc { # Add your templates with higher priority (higher number = higher priority) settings.templateRootPaths { 10 = EXT:my_sitepackage/Resources/Private/Templates/ @@ -208,16 +215,28 @@ Add the template path to your TypoScript setup: } } + # Captioned images render as
blocks and are processed via + # externalBlocks.figure.stdWrap.preUserFunc (renderFigure). The same + # settings.* block has to be duplicated here for figure rendering. + lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc { + settings.templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + settings.partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } + settings.layoutRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + } + } + .. note:: - The configuration must be placed within ``lib.parseFunc_RTE.tags.img`` - (not directly in ``lib.parseFunc_RTE``). The same configuration can be - added to ``externalBlocks.figure.stdWrap`` for images wrapped in - ``
`` blocks (captioned images). Figures are processed via - ``externalBlocks``, not ``tags.figure`` — placing the configuration - under ``tags.figure`` has no effect. Inline images wrapped in ```` - are rendered by ``tags.img`` (recursively, inside the link wrapper), so - they already pick up the configuration defined under ``tags.img``. + Figures are processed via ``externalBlocks``, not ``tags.figure`` — + placing the configuration under ``tags.figure`` has no effect. Inline + images wrapped in ```` are rendered by ``tags.img`` (recursively, + inside the link wrapper), so they already pick up the configuration + defined under ``tags.img.preUserFunc``. Step 3: Create override templates --------------------------------- diff --git a/Resources/AGENTS.md b/Resources/AGENTS.md index 1980d907..63d68268 100644 --- a/Resources/AGENTS.md +++ b/Resources/AGENTS.md @@ -66,10 +66,24 @@ Figure wrappers are only created when there is a caption. Alignment classes with ## Template Override Mechanism -Integrators can override templates via TypoScript: +Integrators can override templates via TypoScript. The `settings.*` block +must live inside `preUserFunc.` because TYPO3 only passes +`$conf['preUserFunc.']` to the rendering callable (see +`ContentObjectRenderer::stdWrap_preUserFunc()`): ```typoscript -lib.parseFunc_RTE.tags.img { +lib.parseFunc_RTE.tags.img.preUserFunc { + settings.templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + settings.partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } +} + +# Figures (captioned images) need the same block under the +# externalBlocks.figure.stdWrap.preUserFunc that runs renderFigure(). +lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc { settings.templateRootPaths { 10 = EXT:my_sitepackage/Resources/Private/Templates/ } From fab386f29f0ddc1717f6a9d348b439f06be6339b Mon Sep 17 00:00:00 2001 From: Marek Skopal Date: Fri, 5 Jun 2026 15:51:28 +0200 Subject: [PATCH 2/2] docs: nest settings block and use TYPO3 dot-suffix convention Address review feedback: - Replace `settings.*` with `settings.` (canonical TYPO3 sub-property notation) in all prose. - Nest the override example as `preUserFunc { settings { templateRootPaths { ... } } }` instead of the flat `preUserFunc.settings.templateRootPaths`, which gets awkward at three levels deep. Signed-off-by: Marek Skopal --- .../ImageRendering/setup.typoscript | 26 +++++++----- Documentation/Examples/Template-Overrides.rst | 40 ++++++++++--------- Resources/AGENTS.md | 26 +++++++----- 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/Configuration/TypoScript/ImageRendering/setup.typoscript b/Configuration/TypoScript/ImageRendering/setup.typoscript index e01f5bef..dce825fc 100755 --- a/Configuration/TypoScript/ImageRendering/setup.typoscript +++ b/Configuration/TypoScript/ImageRendering/setup.typoscript @@ -25,22 +25,26 @@ lib.parseFunc_RTE { # IMPORTANT: Use the extension key "rte_ckeditor_image" (underscores) in # EXT: paths, NOT the Composer package name "rte-ckeditor-image" (hyphens). # - # To override, add your paths with priority > 0 INSIDE preUserFunc.* — + # To override, add your paths with priority > 0 INSIDE preUserFunc. — # TYPO3's stdWrap_preUserFunc only forwards $conf['preUserFunc.'] to the - # callable, so a settings.* block placed as a sibling of preUserFunc + # callable, so a settings. block placed as a sibling of preUserFunc # never reaches ImageRenderingService::buildTemplatePaths(). # - # preUserFunc.settings.templateRootPaths { - # 10 = EXT:my_sitepackage/Resources/Private/Templates/ - # } - # preUserFunc.settings.partialRootPaths { - # 10 = EXT:my_sitepackage/Resources/Private/Partials/ - # } - # preUserFunc.settings.layoutRootPaths { - # 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + # preUserFunc { + # settings { + # templateRootPaths { + # 10 = EXT:my_sitepackage/Resources/Private/Templates/ + # } + # partialRootPaths { + # 10 = EXT:my_sitepackage/Resources/Private/Partials/ + # } + # layoutRootPaths { + # 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + # } + # } # } # - # The same settings.* block must also be added under + # The same settings. block must also be added under # lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc for # captioned (figure-wrapped) images. # diff --git a/Documentation/Examples/Template-Overrides.rst b/Documentation/Examples/Template-Overrides.rst index 6827c06b..c2770d84 100644 --- a/Documentation/Examples/Template-Overrides.rst +++ b/Documentation/Examples/Template-Overrides.rst @@ -190,7 +190,7 @@ In your site package, create the override directory: Step 2: Configure TypoScript ---------------------------- -Add the template path to your TypoScript setup. The ``settings.*`` block +Add the template path to your TypoScript setup. The ``settings.`` block must live **inside** ``preUserFunc.`` — that is the only sub-array TYPO3 forwards to the rendering callable (see :php:`ContentObjectRenderer::stdWrap_preUserFunc()`, which passes only @@ -204,29 +204,33 @@ effect — the configuration never reaches lib.parseFunc_RTE.tags.img.preUserFunc { # Add your templates with higher priority (higher number = higher priority) - settings.templateRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Templates/ - } - settings.partialRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Partials/ - } - settings.layoutRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + settings { + templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } + layoutRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + } } } # Captioned images render as
blocks and are processed via # externalBlocks.figure.stdWrap.preUserFunc (renderFigure). The same - # settings.* block has to be duplicated here for figure rendering. + # settings. block has to be duplicated here for figure rendering. lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc { - settings.templateRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Templates/ - } - settings.partialRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Partials/ - } - settings.layoutRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + settings { + templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } + layoutRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Layouts/ + } } } diff --git a/Resources/AGENTS.md b/Resources/AGENTS.md index 63d68268..b0a75ccb 100644 --- a/Resources/AGENTS.md +++ b/Resources/AGENTS.md @@ -66,29 +66,33 @@ Figure wrappers are only created when there is a caption. Alignment classes with ## Template Override Mechanism -Integrators can override templates via TypoScript. The `settings.*` block +Integrators can override templates via TypoScript. The `settings.` block must live inside `preUserFunc.` because TYPO3 only passes `$conf['preUserFunc.']` to the rendering callable (see `ContentObjectRenderer::stdWrap_preUserFunc()`): ```typoscript lib.parseFunc_RTE.tags.img.preUserFunc { - settings.templateRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Templates/ - } - settings.partialRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Partials/ + settings { + templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } } } # Figures (captioned images) need the same block under the # externalBlocks.figure.stdWrap.preUserFunc that runs renderFigure(). lib.parseFunc_RTE.externalBlocks.figure.stdWrap.preUserFunc { - settings.templateRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Templates/ - } - settings.partialRootPaths { - 10 = EXT:my_sitepackage/Resources/Private/Partials/ + settings { + templateRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Templates/ + } + partialRootPaths { + 10 = EXT:my_sitepackage/Resources/Private/Partials/ + } } } ```