feat(!!!): add TYPO3 v14 support and replace static templates with native content elements#31
Conversation
Replace 4 pattern content elements (Colors, Fonts, Icons, Images) previously rendered via bw-static-template with proper TYPO3 content elements using IRRE child records. Move bw-static-template from require to suggest. Remove the Templates pattern and TemplateViewHelper entirely.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds TYPO3 v14 support and new styleguide content elements (Colors, Fonts, Icons, Images): introduces TCA and DB schema, a backend preview renderer, Fluid templates and ViewHelper signature updates, removes TemplateViewHelper/bw_static_template usage, updates DDEV scripts and documentation, and adjusts fixtures and composer metadata. Changes
Sequence Diagram(s)sequenceDiagram
participant PageModule as Backend Page Module
participant Preview as StyleguidePreviewRenderer
participant DB as TYPO3 Database
participant FS as File System / PathUtility
participant Template as Fluid Template Renderer
PageModule->>Preview: renderPageModulePreviewContent(GridColumnItem)
Preview->>Preview: inspect CType
alt colors/fonts/images
Preview->>DB: query tx_metypo3styleguide_* child records
DB-->>Preview: return records
Preview->>Template: render preview template (Preview/*)
Template-->>Preview: HTML
else icons
Preview->>FS: resolve icons directory path & list files
FS-->>Preview: list files (capped)
Preview->>Template: render icons preview template
Template-->>Preview: HTML
end
Preview-->>PageModule: return preview HTML
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
ext_emconf.php (1)
23-31:⚠️ Potential issue | 🟠 MajorUpdate ext_emconf.php TYPO3 constraint to include v14 support.
The
ext_emconf.phpconstraint on line 26 caps TYPO3 at13.4.99, conflicting with the stated support for TYPO3 14 declared incomposer.json(^12.0 || ^13.0 || ^14.0). This mismatch will prevent installation via Extension Manager on TYPO3 14 despite the extension being compatible.Proposed fix
- 'typo3' => '12.4.0-13.4.99', + 'typo3' => '12.4.0-14.4.99',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ext_emconf.php` around lines 23 - 31, The TYPO3 version constraint in ext_emconf.php under the 'constraints' -> 'depends' -> 'typo3' entry currently limits versions to '12.4.0-13.4.99'; update that constraint to include TYPO3 v14 by expanding the upper bound (for example to '12.4.0-14.99.99' or similar) so it matches composer.json's supported ranges (^12.0 || ^13.0 || ^14.0) and allows installation on TYPO3 14 via the Extension Manager.Classes/ViewHelpers/FilesViewHelper.php (1)
44-48:⚠️ Potential issue | 🟠 MajorHandle
scandir()failure explicitly.Line 44 assumes
scandir($path)always returns an array. Although the code validatesis_dir($path)at line 39, this is insufficient;scandir()can still returnfalsedue to permission issues or race conditions (directory becomes unreadable between theis_dir()check andscandir()call). This results in aTypeErrorwhen theforeachtries to iterate overfalse. Similar code inClasses/Preview/StyleguidePreviewRenderer.phpcorrectly handles this with an explicitfalsecheck.Add an explicit check for
scandir()failure:Proposed fix
+ $entries = scandir($path); + if ($entries === false) { + throw new InvalidArgumentException('The provided path is not readable: '.$path, 4247501750); + } + $files = []; - foreach (scandir($path) as $file) { + foreach ($entries as $file) { if ('.' !== $file && '..' !== $file && is_file($path.'/'.$file)) { $files[] = $file; } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/ViewHelpers/FilesViewHelper.php` around lines 44 - 48, The foreach in FilesViewHelper.php assumes scandir($path) returns an array and will TypeError on false; update the code that calls scandir($path) (inside the FilesViewHelper class/method that currently checks is_dir($path)) to store the result in a variable, check it !== false before iterating, and handle the false case (e.g., treat as empty array or log/return early) similar to the handling in Classes/Preview/StyleguidePreviewRenderer.php so the loop only runs on a valid array from scandir.Classes/ViewHelpers/ContrastColorViewHelper.php (1)
37-43:⚠️ Potential issue | 🟡 MinorLength-only validation accepts invalid HEX color strings.
Line 37 only checks length, so values like
GGGGGGpass and compute as unintended RGB values.✅ Proposed validation tightening
$hexColor = ltrim((string) $this->arguments['color'], '#'); - if (6 !== strlen($hexColor)) { + if (!preg_match('/^[0-9A-Fa-f]{6}$/', $hexColor)) { throw new InvalidArgumentException('Invalid HEX color code: '.$this->arguments['color'], 4518636088); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/ViewHelpers/ContrastColorViewHelper.php` around lines 37 - 43, The length-only check for $hexColor in ContrastColorViewHelper accepts non-hex characters (e.g., "GGGGGG"); update validation to ensure $hexColor contains only valid hex digits (0-9, a-f, A-F) after stripping an optional leading '#' before proceeding to hexdec conversions, and if invalid throw the same InvalidArgumentException (use the existing message/exception type) so only proper HEX strings reach the substr/hexdec logic.
🧹 Nitpick comments (5)
Classes/ViewHelpers/Format/FilenameViewHelper.php (1)
26-33:filenameargument is registered but ignored inrender().Line 28 declares
filename, but Line 33 always reads children. Self-closing usage withfilename="..."won’t work as expected.♻️ Proposed adjustment
public function render(): string { - $value = $this->renderChildren(); + $value = $this->arguments['filename'] ?? $this->renderChildren(); return pathinfo((string) $value, \PATHINFO_FILENAME); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/ViewHelpers/Format/FilenameViewHelper.php` around lines 26 - 33, The registered 'filename' argument is never used in render(), so update the render() method in FilenameViewHelper to prefer the passed argument (from $this->arguments['filename'] or $this->getArgument('filename')) and only call $this->renderChildren() as a fallback when the argument is null/empty; ensure you keep the existing formatting logic that consumes the computed $value so both self-closing usage (filename="...") and tag content work the same..ddev/commands/web/.install-13 (1)
10-13: Consider removing the commented placeholder composer block.These commented lines look like unfinished setup logic and add noise to operational scripts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.ddev/commands/web/.install-13 around lines 10 - 13, Remove the leftover commented placeholder composer block (the lines beginning with "#_progress", "# composer req x/y:'^1.0' \", and "#_done") so the script has no noisy unused comments; simply delete those commented lines from the install script (or replace them with an explanatory single-line comment if you want a note), ensuring no functional change to the surrounding script.Configuration/TypoScript/setup.typoscript (1)
13-20: Optional: extract shared query-processor config to reduce drift.The three DatabaseQueryProcessor blocks duplicate
where, marker, and sorting setup. A shared base object would simplify maintenance.♻️ Possible TypoScript refactor
+lib.metypo3styleguideIrreProcessor = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor +lib.metypo3styleguideIrreProcessor { + where = parentid=###uid### AND parenttable='tt_content' + markers.uid.field = uid + orderBy = sorting +} + tt_content { metypo3styleguide_colors { - dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor - dataProcessing.10 { - table = tx_metypo3styleguide_color - where = parentid=###uid### AND parenttable='tt_content' - markers.uid.field = uid - orderBy = sorting - as = colors - } + dataProcessing.10 < lib.metypo3styleguideIrreProcessor + dataProcessing.10.table = tx_metypo3styleguide_color + dataProcessing.10.as = colors } metypo3styleguide_fonts { - dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor - dataProcessing.10 { - table = tx_metypo3styleguide_font - where = parentid=###uid### AND parenttable='tt_content' - markers.uid.field = uid - orderBy = sorting - as = fonts - } + dataProcessing.10 < lib.metypo3styleguideIrreProcessor + dataProcessing.10.table = tx_metypo3styleguide_font + dataProcessing.10.as = fonts } metypo3styleguide_images { - dataProcessing.10 = TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor - dataProcessing.10 { - table = tx_metypo3styleguide_image - where = parentid=###uid### AND parenttable='tt_content' - markers.uid.field = uid - orderBy = sorting - as = images - } + dataProcessing.10 < lib.metypo3styleguideIrreProcessor + dataProcessing.10.table = tx_metypo3styleguide_image + dataProcessing.10.as = images } }Also applies to: 26-33, 44-51
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Configuration/TypoScript/setup.typoscript` around lines 13 - 20, The three DatabaseQueryProcessor blocks (e.g., dataProcessing.10 using TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor with table, where, markers.uid.field and orderBy = sorting) duplicate the same where/marker/sorting settings; extract those shared settings into a single reusable TypoScript object (e.g., a base processor object) and then include or reference that base from each dataProcessing entry so each block only overrides the unique pieces like table and as, reducing drift and keeping where/markers/orderBy consistent across dataProcessing.10, dataProcessing.26 and dataProcessing.44.Configuration/TCA/Overrides/tt_content.php (1)
218-292: Consider extracting shared type config to reduceshowitemduplication.Lines 218–292 repeat nearly identical layout blocks for four types. A small shared base array/string would reduce drift risk in future updates.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Configuration/TCA/Overrides/tt_content.php` around lines 218 - 292, Extract the duplicated 'showitem' definition into a single shared variable (e.g. $styleguideShowItem or $styleguideShowItemBase) and reuse it for each type ('metypo3styleguide_colors', 'metypo3styleguide_fonts', 'metypo3styleguide_icons', 'metypo3styleguide_images') by appending only the type‑specific field (tx_metypo3styleguide_colors, tx_metypo3styleguide_fonts, tx_metypo3styleguide_icons_path, tx_metypo3styleguide_images) to the base string/array; keep the 'previewRenderer' => StyleguidePreviewRenderer::class assignment for each type and replace the inline duplicated 'showitem' blocks with the shared variable to avoid duplication and drift.Classes/Preview/StyleguidePreviewRenderer.php (1)
135-159: Filter icon directory to image files only and handle missing web paths.Line 135 uses
scandir()to load all files without extension filtering. In directories containing mixed file types, this forces thumbnail attempts on non-image files, causing broken image requests and unnecessary processing.Replace
scandir()withFilesystemIteratorand filter for image extensions. Additionally, check thatPathUtility::getAbsoluteWebPath()returns a non-empty string before rendering the image tag, consistent with the pattern used inrenderImagesPreview().♻️ Proposed refactor
- $files = scandir($absDir); - if (false === $files) { - return '<span style="font-size:11px;color:`#666`;">'.htmlspecialchars($path, ENT_QUOTES).'</span>'; - } - $items = ''; $count = 0; - foreach ($files as $file) { - if ('.' === $file || '..' === $file || !is_file($absDir.'/'.$file)) { + $iterator = new \FilesystemIterator($absDir, \FilesystemIterator::SKIP_DOTS); + $allowed = ['svg', 'png', 'jpg', 'jpeg', 'gif', 'webp']; + foreach ($iterator as $entry) { + if (!$entry->isFile()) { continue; } + $extension = strtolower($entry->getExtension()); + if (!in_array($extension, $allowed, true)) { + continue; + } ++$count; if ($count > 20) { $items .= '<div style="display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;font-size:11px;color:`#666`;">…</div>'; break; } - $webPath = PathUtility::getAbsoluteWebPath($absDir.'/'.$file); - $name = htmlspecialchars(pathinfo($file, \PATHINFO_FILENAME), ENT_QUOTES); + $filePath = $entry->getPathname(); + $webPath = PathUtility::getAbsoluteWebPath($filePath); + if ('' === $webPath) { + continue; + } + $name = htmlspecialchars(pathinfo($entry->getFilename(), \PATHINFO_FILENAME), ENT_QUOTES); $items .= '<div style="display:inline-block;margin:0 4px 4px 0;text-align:center;" title="'.$name.'">' .'<img src="'.htmlspecialchars($webPath, ENT_QUOTES).'" alt="'.$name.'" style="width:32px;height:32px;object-fit:contain;" loading="lazy" />' .'</div>'; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/Preview/StyleguidePreviewRenderer.php` around lines 135 - 159, Replace the raw scandir() loop with a FilesystemIterator over $absDir and only iterate files whose extensions match allowed image types (e.g. jpg,jpeg,png,gif,webp,svg), preserving the existing $count/limit and thumbnail markup logic; for each candidate, call PathUtility::getAbsoluteWebPath($absDir.'/'.$file) and skip rendering if it returns an empty string (mirroring renderImagesPreview()'s pattern) so no <img> tags are emitted for non-image files or missing web paths, and keep using htmlspecialchars for $name and the existing loading="lazy"/thumb sizing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.ddev/.setup/scripts/utils.sh:
- Around line 33-34: The script commented out the initial file-descriptor setup
(the two exec lines) but _done() still attempts to restore them with exec 1>&3
2>&4, causing "bad file descriptor" in spinner mode; fix by either restoring the
original exec lines (re-enable the exec 3>&1 4>&2 and exec >/dev/null 2>&1 that
open fd 3 and 4) or modify _done() to only restore if fds 3 and 4 are open
(check /proc/self/fd or use `exec 3>&-` guards) so the exec 1>&3 2>&4 call is
never invoked when those descriptors were not created.
In @.ddev/commands/web/.install-12:
- Line 5: The top comment stating "Pre-setup function for TYPO3 version 13" is
incorrect relative to the call to pre_setup 12; update the comment to match the
actual target version or change the invoked helper to match the
comment—specifically either change the comment text to "TYPO3 version 12" or
replace the call to pre_setup 12 with pre_setup 13 so the file's comment and the
pre_setup invocation (pre_setup 12) are consistent; ensure the phrase
referencing the version in the comment matches the symbol pre_setup X used
below.
In @.github/workflows/release.yml:
- Line 10: Replace the mutable ref `@main` in the reusable workflow reference
`uses: jackd248/reusable-github-actions/.github/workflows/release.yml@main` with
a pinned commit SHA; obtain the exact SHA for the repository's main branch
(e.g., via GitHub API or git ls-remote) and update the uses line to
`...@<commit-sha>` so the workflow points to an immutable commit instead of
`@main`.
In `@Classes/Preview/StyleguidePreviewRenderer.php`:
- Around line 216-230: The getChildRecords method is performing a DB query even
when $parentId is 0 (unsaved/new CE); update getChildRecords(string $table, int
$parentId): array to early-return an empty array when $parentId is 0 (or
non-positive) to avoid unnecessary queries and accidental matching of orphan
rows, then only proceed to build and execute the ConnectionPool/QueryBuilder
query when $parentId > 0.
In `@Configuration/TCA/tx_metypo3styleguide_color.php`:
- Around line 19-27: The table schema for tx_metypo3styleguide_color is missing
the standard TYPO3 ctrl columns (tstamp, crdate, deleted, hidden, sorting);
update ext_tables.sql to add these columns to the CREATE TABLE for
tx_metypo3styleguide_color (include tstamp int(11) unsigned, crdate int(11)
unsigned, deleted tinyint(4) unsigned, hidden tinyint(4), sorting int(11) plus
appropriate DEFAULT/NOT NULL definitions) and ensure PRIMARY KEY (uid) and KEY
parentid exist so the TCA fields referenced in ctrl (tstamp, crdate, deleted,
sorting, enablecolumns.disabled => hidden) align with the DB schema.
- Around line 46-52: Replace the current TCA input configuration that uses
'type' => 'input' (and the attributes 'max' => 7 and 'eval' => 'trim') with the
native color field config by setting 'config' => ['type' => 'color'] so the
field enforces `#RRGGBB` format; keep 'required' if needed and remove 'max' and
'eval' because the core color type handles trimming and length validation.
Target the array that currently contains 'type' => 'input', 'size' => 10, 'max'
=> 7, 'eval' => 'trim', 'required' => true, 'placeholder' => '#000000' and
replace it with a config using 'config' => ['type' => 'color'] (retaining or
adjusting 'placeholder'/'required' as appropriate).
In `@Configuration/TCA/tx_metypo3styleguide_font.php`:
- Around line 54-62: The TCA currently lets arbitrary text into the font_weight
field (identifier 'font_weight') which is later injected into inline CSS in
Resources/Private/Templates/Fonts.html; change the TCA config from an
unrestricted 'type' => 'input' to a constrained choice (e.g., 'type' => 'select'
with 'items' listing valid CSS font-weight tokens:
100,200,300,400,500,600,700,800,900 and optionally 'normal'/'bold'), set a
sensible default/placeholder (e.g., '400') and ensure the value saved is the
numeric/string token expected by the template; optionally add 'eval' => 'int' if
you keep an input but prefer numeric validation — update 'font_weight' config
accordingly so invalid tokens cannot be entered and thus won't break the inline
CSS in Fonts.html.
In `@Configuration/TCA/tx_metypo3styleguide_image.php`:
- Around line 46-52: The TCA for the 'path' field currently only trims input and
allows arbitrary strings; update the field definition in
tx_metypo3styleguide_image.php (the array entry for 'path') to validate EXT:
resource syntax by adding a stricter eval: either include a whitelist check
(e.g. use an is_in-style eval if you register allowed prefixes) or, preferably,
register and use a custom eval class (e.g.
Vendor\YourExt\Evaluation\ExtPathEval) and add its token to the eval string (for
example 'eval' => 'trim,required,tx_yourext_extpatheval') so only valid
"EXT:extensionKey/..." paths are persisted and passed to
GeneralUtility::getFileAbsFileName().
In `@ext_tables.sql`:
- Around line 10-33: The child tables tx_metypo3styleguide_color,
tx_metypo3styleguide_font and tx_metypo3styleguide_image must define the sorting
column referenced by your inline configs; update each CREATE TABLE
(tx_metypo3styleguide_color, tx_metypo3styleguide_font,
tx_metypo3styleguide_image) to add a sorting int(11) DEFAULT 0 NOT NULL column
and remove any trailing commas in the column list so the SQL is valid; this
ensures foreign_sortby => 'sorting' works when TYPO3 persists/reorders inline
children.
In `@README.md`:
- Line 8: The badge markdown has an empty link destination "[]()", which
makes the badge non-clickable; update that markdown to include a valid URL
target (for example the project homepage, release/tags page, or the TYPO3
compatibility docs) by replacing the empty parentheses with the intended
destination so the badge becomes a functional link.
In `@Resources/Private/Templates/Colors.html`:
- Around line 15-17: The template currently calls sg:contrastColor with
unvalidated editor input (variable contrastColor using {color.data.color}),
which can throw in Classes/ViewHelpers/ContrastColorViewHelper.php for malformed
HEX values; update the Colors.html template to validate or sanitize
{color.data.color} before calling sg:contrastColor and wrap the helper
invocation in a fail-soft fallback: check the string format (e.g., regex for
`#RRGGBB` or `#RGB`) and only call sg:contrastColor when valid, otherwise set
contrastColor to a safe default (e.g., "#000000" or computed default) so
rendering never throws; ensure the change references the contrastColor variable
and uses the same sg:contrastColor helper name.
In `@Resources/Private/Templates/Icons.html`:
- Line 17: Normalize data.tx_metypo3styleguide_icons_path before concatenation
so it always has exactly one trailing slash; update the template that builds the
src (the <img> using {sg:uri.resourcePath(path:
'{data.tx_metypo3styleguide_icons_path}{file}')} ) to trim any trailing slash
from data.tx_metypo3styleguide_icons_path and then append a single "/" before
{file} (or use a ViewHelper that joins path segments), ensuring the resourcePath
always receives a valid path with one separator between base path and file.
---
Outside diff comments:
In `@Classes/ViewHelpers/ContrastColorViewHelper.php`:
- Around line 37-43: The length-only check for $hexColor in
ContrastColorViewHelper accepts non-hex characters (e.g., "GGGGGG"); update
validation to ensure $hexColor contains only valid hex digits (0-9, a-f, A-F)
after stripping an optional leading '#' before proceeding to hexdec conversions,
and if invalid throw the same InvalidArgumentException (use the existing
message/exception type) so only proper HEX strings reach the substr/hexdec
logic.
In `@Classes/ViewHelpers/FilesViewHelper.php`:
- Around line 44-48: The foreach in FilesViewHelper.php assumes scandir($path)
returns an array and will TypeError on false; update the code that calls
scandir($path) (inside the FilesViewHelper class/method that currently checks
is_dir($path)) to store the result in a variable, check it !== false before
iterating, and handle the false case (e.g., treat as empty array or log/return
early) similar to the handling in Classes/Preview/StyleguidePreviewRenderer.php
so the loop only runs on a valid array from scandir.
In `@ext_emconf.php`:
- Around line 23-31: The TYPO3 version constraint in ext_emconf.php under the
'constraints' -> 'depends' -> 'typo3' entry currently limits versions to
'12.4.0-13.4.99'; update that constraint to include TYPO3 v14 by expanding the
upper bound (for example to '12.4.0-14.99.99' or similar) so it matches
composer.json's supported ranges (^12.0 || ^13.0 || ^14.0) and allows
installation on TYPO3 14 via the Extension Manager.
---
Nitpick comments:
In @.ddev/commands/web/.install-13:
- Around line 10-13: Remove the leftover commented placeholder composer block
(the lines beginning with "#_progress", "# composer req x/y:'^1.0' \", and
"#_done") so the script has no noisy unused comments; simply delete those
commented lines from the install script (or replace them with an explanatory
single-line comment if you want a note), ensuring no functional change to the
surrounding script.
In `@Classes/Preview/StyleguidePreviewRenderer.php`:
- Around line 135-159: Replace the raw scandir() loop with a FilesystemIterator
over $absDir and only iterate files whose extensions match allowed image types
(e.g. jpg,jpeg,png,gif,webp,svg), preserving the existing $count/limit and
thumbnail markup logic; for each candidate, call
PathUtility::getAbsoluteWebPath($absDir.'/'.$file) and skip rendering if it
returns an empty string (mirroring renderImagesPreview()'s pattern) so no <img>
tags are emitted for non-image files or missing web paths, and keep using
htmlspecialchars for $name and the existing loading="lazy"/thumb sizing.
In `@Classes/ViewHelpers/Format/FilenameViewHelper.php`:
- Around line 26-33: The registered 'filename' argument is never used in
render(), so update the render() method in FilenameViewHelper to prefer the
passed argument (from $this->arguments['filename'] or
$this->getArgument('filename')) and only call $this->renderChildren() as a
fallback when the argument is null/empty; ensure you keep the existing
formatting logic that consumes the computed $value so both self-closing usage
(filename="...") and tag content work the same.
In `@Configuration/TCA/Overrides/tt_content.php`:
- Around line 218-292: Extract the duplicated 'showitem' definition into a
single shared variable (e.g. $styleguideShowItem or $styleguideShowItemBase) and
reuse it for each type ('metypo3styleguide_colors', 'metypo3styleguide_fonts',
'metypo3styleguide_icons', 'metypo3styleguide_images') by appending only the
type‑specific field (tx_metypo3styleguide_colors, tx_metypo3styleguide_fonts,
tx_metypo3styleguide_icons_path, tx_metypo3styleguide_images) to the base
string/array; keep the 'previewRenderer' => StyleguidePreviewRenderer::class
assignment for each type and replace the inline duplicated 'showitem' blocks
with the shared variable to avoid duplication and drift.
In `@Configuration/TypoScript/setup.typoscript`:
- Around line 13-20: The three DatabaseQueryProcessor blocks (e.g.,
dataProcessing.10 using TYPO3\CMS\Frontend\DataProcessing\DatabaseQueryProcessor
with table, where, markers.uid.field and orderBy = sorting) duplicate the same
where/marker/sorting settings; extract those shared settings into a single
reusable TypoScript object (e.g., a base processor object) and then include or
reference that base from each dataProcessing entry so each block only overrides
the unique pieces like table and as, reducing drift and keeping
where/markers/orderBy consistent across dataProcessing.10, dataProcessing.26 and
dataProcessing.44.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 35f38f84-6395-493c-bab2-5ab1079ac7cc
⛔ Files ignored due to path filters (9)
Documentation/Images/content-element-wizard.jpgis excluded by!**/*.jpgResources/Public/Icons/Extension.svgis excluded by!**/*.svgResources/Public/Icons/content-styleguide-colors.svgis excluded by!**/*.svgResources/Public/Icons/content-styleguide-fonts.svgis excluded by!**/*.svgResources/Public/Icons/content-styleguide-headline.svgis excluded by!**/*.svgResources/Public/Icons/content-styleguide-icons.svgis excluded by!**/*.svgResources/Public/Icons/content-styleguide-images.svgis excluded by!**/*.svgResources/Public/Icons/page-styleguide-hidden.svgis excluded by!**/*.svgResources/Public/Icons/page-styleguide.svgis excluded by!**/*.svg
📒 Files selected for processing (46)
.ddev/.setup/scripts/utils.sh.ddev/commands/web/.install-11.ddev/commands/web/.install-12.ddev/commands/web/.install-13.ddev/commands/web/.install-14.ddev/commands/web/11.ddev/config.typo3-setup.yaml.ddev/docker-compose.typo3-setup.yaml.github/workflows/release.ymlClasses/Preview/StyleguidePreviewRenderer.phpClasses/ViewHelpers/ContrastColorViewHelper.phpClasses/ViewHelpers/FilesViewHelper.phpClasses/ViewHelpers/Format/FilenameViewHelper.phpClasses/ViewHelpers/Render/TemplateViewHelper.phpClasses/ViewHelpers/Uri/ResourcePathViewHelper.phpConfiguration/Icons.phpConfiguration/TCA/Overrides/tt_content.phpConfiguration/TCA/tx_metypo3styleguide_color.phpConfiguration/TCA/tx_metypo3styleguide_font.phpConfiguration/TCA/tx_metypo3styleguide_image.phpConfiguration/TsConfig/ContentElements/Colors.tsconfigConfiguration/TsConfig/ContentElements/Fonts.tsconfigConfiguration/TsConfig/ContentElements/Icons.tsconfigConfiguration/TsConfig/ContentElements/Images.tsconfigConfiguration/TsConfig/ContentElements/TechnicalHeadline.tsconfigConfiguration/TsConfig/TCEFORM.tsconfigConfiguration/TypoScript/constants.typoscriptConfiguration/TypoScript/setup.typoscriptDocumentation/ContentElement.mdDocumentation/Patterns.mdDocumentation/StaticTemplates.mdDocumentation/ViewHelpers/Classes/TemplateViewHelper.mdREADME.mdResources/Private/Language/de.locallang.xlfResources/Private/Language/locallang.xlfResources/Private/Templates/Colors.htmlResources/Private/Templates/Fonts.htmlResources/Private/Templates/Icons.htmlResources/Private/Templates/Images.htmlResources/Private/Templates/Patterns/Colors.htmlResources/Private/Templates/Patterns/Templates.htmlTests/Acceptance/Fixtures/data.xmlcomposer-unused.phpcomposer.jsonext_emconf.phpext_tables.sql
💤 Files with no reviewable changes (9)
- Resources/Private/Templates/Patterns/Colors.html
- Classes/ViewHelpers/Render/TemplateViewHelper.php
- Configuration/TypoScript/constants.typoscript
- Documentation/Patterns.md
- Documentation/StaticTemplates.md
- .ddev/commands/web/11
- Resources/Private/Templates/Patterns/Templates.html
- Documentation/ViewHelpers/Classes/TemplateViewHelper.md
- .ddev/commands/web/.install-11
| 'type' => 'input', | ||
| 'size' => 50, | ||
| 'max' => 255, | ||
| 'eval' => 'trim', | ||
| 'required' => true, | ||
| 'placeholder' => 'EXT:sitepackage/Resources/Public/Images/logo.svg', | ||
| ], |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
TYPO3 v14 TCA input validation EXT resource paths
💡 Result:
In TYPO3 v14 you should store and validate “system resource identifiers” (not physical paths like typo3conf/ext/...). TYPO3’s System Resource API supports these formats: EXT:ext_key/... (still supported), the recommended PKG:vendor/package:..., FAL:<storageUid>:/..., app resources via PKG:typo3/app:..., and URLs like https://... / URI:/.... Legacy identifiers such as typo3conf/ext/my_ext/... are no longer handled consistently and should be migrated to EXT:/PKG:. [1]
For a TCA type => 'input' field, TYPO3’s built-in validation is limited to the usual eval keywords plus custom eval classes:
- Use
eval => 'is_in'together with theis_inproperty to whitelist allowed characters (e.g. letters, digits,:,/,.,_,-). [2] - For real validation of “allowed resource syntaxes” (EXT/PKG/FAL/URI), implement a custom TCA eval (client + server): TCA
evalsupports registeringVendor\Extension\...evaluators, executed when saving;is_inis also passed to the evaluator. [2]
If you want to allow app resources, note TYPO3 restricts which app/public folders are allowed by default, and additional allowed folders are configured via $GLOBALS['TYPO3_CONF_VARS']['FE']['addAllowedPaths']. [1]
Sources
[1] TYPO3 v14 Core Changelog – System resource API (Feature #107537) https://docs.typo3.org/c/typo3/cms-core/main/en-us/Changelog/14.0/Feature-107537-SystemResourceAPIForSystemFileAccessAndPublicUriGeneration.html
[2] TYPO3 TCA Reference (main/v14) – type='input', eval, is_in, custom eval classes https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ColumnsConfig/Type/Input/Index.html
🌐 Web query:
TYPO3 TCA validators for file paths and resources
💡 Result:
In TYPO3 TCA there isn’t a single “file path validator” for arbitrary string paths; validation depends on how you model the value (FAL file reference vs. link browser value vs. plain input). These are the usual options:
1) Prefer FAL references: type => 'file' (recommended)
Use the dedicated TCA file field type and restrict by extension via allowed (and optionally disallowed). allowed supports reserved sets like common-image-types, common-text-types, common-media-types, plus explicit extensions. Array notation works reliably in TYPO3 v12.4.1+/v13.1+. [1]
'my_asset' => [
'config' => [
'type' => 'file',
'allowed' => 'common-image-types,svg,pdf',
// 'disallowed' => 'php,phar', // if needed
'maxitems' => 1,
],
],This stores a resource reference (sys_file_reference), not a brittle filesystem path. [1]
2) If it’s a link field (page/url/file/folder): type => 'input', renderType => 'inputLink'
Use the link browser control and restrict selectable files by extension using fieldControl.linkPopup.options.allowedExtensions. [2]
'my_link' => [
'config' => [
'type' => 'input',
'renderType' => 'inputLink',
'fieldControl' => [
'linkPopup' => [
'options' => [
'allowedExtensions' => 'pdf,docx',
// optionally hide link modes:
// 'blindLinkOptions' => 'folder',
],
],
],
],
],Note: this validates the link browser selection options; the stored value is still a link string, not a FAL reference. [2]
3) If you list files from a folder in a select box: fileFolderConfig.allowedExtensions
For type => 'select' with fileFolderConfig, TYPO3 can filter the list of selectable files by extension using fileFolderConfig.allowedExtensions. [3]
4) Plain string “path” field: use eval (or a custom eval)
config.eval for type='input' / type='text' supports many built-in evaluations, and you can register custom form eval classes via $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'] and then reference the class name in eval. [4]
So if you truly must store a path-like string, implement a custom eval that enforces “relative only”, “no ..”, allowed prefixes, etc. (TYPO3 core doesn’t ship a dedicated “filesystem path” eval keyword). [4]
Related (often confused with TCA): Extbase upload validators
If you’re handling uploads via Extbase, TYPO3 mentions default validators like FileNameValidator and FileExtensionMimeTypeConsistencyValidator, but that’s Extbase runtime validation, not TCA field validation. [5]
Sources:
[1] TCA type file / allowed (TYPO3 TCA Reference) (docs.typo3.org)
[2] inputLink / linkPopup.allowedExtensions (TYPO3 TCA Reference) (docs.typo3.org)
[3] fileFolderConfig.allowedExtensions (TYPO3 TCA Reference) (docs.typo3.org)
[4] eval and custom form eval registration (TYPO3 TCA Reference) (docs.typo3.org)
[5] Extbase file upload validators + note about TCA type=file allowed extensions (TYPO3 Core API docs) (docs.typo3.org)
Citations:
- 1: https://docs.typo3.org/m/typo3/reference-tca/main/en-us/ColumnsConfig/Type/File/Index.html?utm_source=openai
- 2: https://docs.typo3.org/m/typo3/reference-tca/11.5/en-us/ColumnsConfig/Type/Input/Properties/LinkPopup.html?utm_source=openai
- 3: https://docs.typo3.org/m/typo3/reference-tca/11.5/en-us/ColumnsConfig/Type/Select/Properties/FileFolderConfig.html?utm_source=openai
- 4: https://docs.typo3.org/m/typo3/reference-tca/11.5/en-us/ColumnsConfig/Type/Input/Properties/Eval.html?utm_source=openai
- 5: https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/ExtensionArchitecture/Extbase/Reference/FileUpload.html?utm_source=openai
🌐 Web query:
TYPO3 v14 TCA input field eval validators options
💡 Result:
In TYPO3 v14, a TCA field with config['type'] = 'input' supports these eval keywords (comma-separated, executed in the given order) [1]:
alpha(a–z, A–Z only)alphanum(letters + digits)alphanum_x(letters + digits +_+-)domainname(valid domain, converts to punycode when needed)is_in(filters to the characters given inconfig['is_in'])lower/uppermd5nospacenum(digits only)trimunique(unique within table, server-side)uniqueInPid(unique within current page/PID, server-side)year(still available, but changed/legacy; TYPO3 recommends usingtype='number'ortype='datetime'instead) [1]
Notable v14 change: “required” is not an eval rule here; use config['required'] => true [2].
Example
'config' => [
'type' => 'input',
'required' => true,
'eval' => 'trim,nospace,lower,uniqueInPid',
],You can also add custom eval rules by registering a PHP class in $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'] and referencing the class name in eval [1].
Sources: [1] [2]
🏁 Script executed:
fd tx_metypo3styleguide_image.php --type fRepository: move-elevator/typo3-styleguide
Length of output: 122
🏁 Script executed:
cat Configuration/TCA/tx_metypo3styleguide_image.phpRepository: move-elevator/typo3-styleguide
Length of output: 2122
🏁 Script executed:
rg "tx_metypo3styleguide_image" --type php -A 5 -B 5 | head -100Repository: move-elevator/typo3-styleguide
Length of output: 6173
🏁 Script executed:
rg "path" Configuration/TCA/tx_metypo3styleguide_image.php -A 2 -B 2Repository: move-elevator/typo3-styleguide
Length of output: 626
🏁 Script executed:
fd -e html -e fluid -e php -type f | xargs rg "tx_metypo3styleguide_image|path" | head -50Repository: move-elevator/typo3-styleguide
Length of output: 8508
🏁 Script executed:
cat Resources/Private/Templates/Images.htmlRepository: move-elevator/typo3-styleguide
Length of output: 1342
🏁 Script executed:
rg "resourcePath|uri" Classes/ -A 3 -B 3 | head -100Repository: move-elevator/typo3-styleguide
Length of output: 56
🏁 Script executed:
find Classes -name "*resourcePath*" -o -name "*uri*" | head -20Repository: move-elevator/typo3-styleguide
Length of output: 56
🏁 Script executed:
rg "uri\.resourcePath|resourcePath" Classes/ -B 5 -A 10Repository: move-elevator/typo3-styleguide
Length of output: 56
🏁 Script executed:
fd -name "*.php" Classes/ViewHelpers | xargs ls -laRepository: move-elevator/typo3-styleguide
Length of output: 2220
🏁 Script executed:
find Classes/ViewHelpers -name "*.php"Repository: move-elevator/typo3-styleguide
Length of output: 308
🏁 Script executed:
cat Classes/ViewHelpers/Uri/ResourcePathViewHelper.phpRepository: move-elevator/typo3-styleguide
Length of output: 1084
Add validation for path field to enforce valid resource syntax.
The field currently accepts arbitrary strings but rendering passes them directly to GeneralUtility::getFileAbsFileName() without validation. Enforce EXT: path format using TCA eval with a character whitelist (is_in) or a custom eval class to prevent malformed paths from being persisted and failing at runtime in the view helper.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Configuration/TCA/tx_metypo3styleguide_image.php` around lines 46 - 52, The
TCA for the 'path' field currently only trims input and allows arbitrary
strings; update the field definition in tx_metypo3styleguide_image.php (the
array entry for 'path') to validate EXT: resource syntax by adding a stricter
eval: either include a whitelist check (e.g. use an is_in-style eval if you
register allowed prefixes) or, preferably, register and use a custom eval class
(e.g. Vendor\YourExt\Evaluation\ExtPathEval) and add its token to the eval
string (for example 'eval' => 'trim,required,tx_yourext_extpatheval') so only
valid "EXT:extensionKey/..." paths are persisted and passed to
GeneralUtility::getFileAbsFileName().
There was a problem hiding this comment.
@coderabbitai The path field stores EXT: resource identifiers resolved at render time via GeneralUtility::getFileAbsFileName(). TYPO3 TCA has no built-in eval for resource path validation, and adding custom validation for a styleguide tool would be over-engineering. Invalid paths simply won't render.
There was a problem hiding this comment.
@konradmichalik, that's a fair point — for a developer-facing styleguide tool, silent graceful failure via GeneralUtility::getFileAbsFileName() returning an empty/null path on invalid input is a perfectly acceptable outcome. Acknowledged, I'll drop this suggestion.
✏️ Learnings added
Learnt from: konradmichalik
Repo: move-elevator/typo3-styleguide PR: 31
File: Configuration/TCA/tx_metypo3styleguide_image.php:46-52
Timestamp: 2026-03-05T12:59:37.991Z
Learning: In the `move-elevator/typo3-styleguide` TYPO3 extension, the `path` field in `Configuration/TCA/tx_metypo3styleguide_image.php` (and similar image/icon path fields) intentionally stores raw `EXT:` resource identifiers without custom TCA eval validation. Invalid paths fail gracefully at render time via `GeneralUtility::getFileAbsFileName()`. Adding a custom eval class for path validation is considered over-engineering for this developer-facing styleguide tool.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
| <f:variable name="contrastColor"> | ||
| <sg:contrastColor color="{color.data.color}"/> | ||
| </f:variable> |
There was a problem hiding this comment.
Invalid color input can hard-fail rendering.
Line 16 invokes sg:contrastColor on editor-provided data; malformed HEX values trigger an exception in Classes/ViewHelpers/ContrastColorViewHelper.php, which can break frontend rendering for this CE. Please add validation/fail-soft handling for invalid color values.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Resources/Private/Templates/Colors.html` around lines 15 - 17, The template
currently calls sg:contrastColor with unvalidated editor input (variable
contrastColor using {color.data.color}), which can throw in
Classes/ViewHelpers/ContrastColorViewHelper.php for malformed HEX values; update
the Colors.html template to validate or sanitize {color.data.color} before
calling sg:contrastColor and wrap the helper invocation in a fail-soft fallback:
check the string format (e.g., regex for `#RRGGBB` or `#RGB`) and only call
sg:contrastColor when valid, otherwise set contrastColor to a safe default
(e.g., "#000000" or computed default) so rendering never throws; ensure the
change references the contrastColor variable and uses the same sg:contrastColor
helper name.
There was a problem hiding this comment.
@coderabbitai The template already guards with <f:if condition="{color.data.color}">, and the TCA field is required with max => 7. An editor would need to intentionally enter malformed data. For a developer-facing styleguide tool, failing loudly on invalid hex codes is the correct behavior — it surfaces misconfiguration immediately rather than silently degrading.
There was a problem hiding this comment.
Rate Limit Exceeded
@konradmichalik have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 57 seconds before sending another message.
| <div class="typo3-styleguide__image typo3-styleguide__icon"> | ||
| <div class="typo3-styleguide__image-box"> | ||
| <img src="{f:uri.resource(path: '{path}{file}')}" alt="{file}"/> | ||
| <img src="{sg:uri.resourcePath(path: '{data.tx_metypo3styleguide_icons_path}{file}')}" alt="{file}"/> |
There was a problem hiding this comment.
Normalize the icon base path before concatenation.
On Line 17, the template assumes data.tx_metypo3styleguide_icons_path always ends with /. If an editor saves EXT:.../Icons (no trailing slash), generated URLs break for all icons.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Resources/Private/Templates/Icons.html` at line 17, Normalize
data.tx_metypo3styleguide_icons_path before concatenation so it always has
exactly one trailing slash; update the template that builds the src (the <img>
using {sg:uri.resourcePath(path:
'{data.tx_metypo3styleguide_icons_path}{file}')} ) to trim any trailing slash
from data.tx_metypo3styleguide_icons_path and then append a single "/" before
{file} (or use a ViewHelper that joins path segments), ensuring the resourcePath
always receives a valid path with one separator between base path and file.
There was a problem hiding this comment.
@coderabbitai Good catch. Added an explicit / separator between the base path and filename in the template to handle paths without trailing slash.
There was a problem hiding this comment.
Rate Limit Exceeded
@konradmichalik have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 56 seconds before sending another message.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
README.md (1)
8-8:⚠️ Potential issue | 🟡 MinorFix the empty badge link target.
Line [8] still uses an empty destination, so the badge is non-functional in rendered Markdown.
Suggested fix
-[]() +[](https://extensions.typo3.org/extension/typo3_styleguide)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` at line 8, The badge link in README.md uses an empty destination ('[]()'), making it non-functional; update that Markdown link by replacing the empty link target with the correct URL (e.g., the project’s TYPO3 support page, release notes, or https://typo3.org) so the badge points to the intended documentation or homepage and remains clickable; edit the exact line containing the '[]()' markup to include the chosen URL.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@README.md`:
- Line 8: The badge link in README.md uses an empty destination ('[]()'), making it non-functional; update that Markdown link
by replacing the empty link target with the correct URL (e.g., the project’s
TYPO3 support page, release notes, or https://typo3.org) so the badge points to
the intended documentation or homepage and remains clickable; edit the exact
line containing the '[]()' markup
to include the chosen URL.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4d28ffef-60a3-4bcd-9ac5-fe817c9b5494
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (1)
README.md
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
Classes/Preview/StyleguidePreviewRenderer.php (1)
99-107: Consider CSS property validation for defense-in-depth.The
fontandweightvalues are inserted into inline CSS. Whilehtmlspecialcharsprevents attribute breakout, it doesn't prevent CSS property injection (e.g.,Arial; background:url(//x)). Since this is backend-only for trusted editors, the risk is minimal, but a simple regex check could add a safety layer.🔧 Optional: Add basic validation
+ /** + * Basic CSS value sanitizer - removes characters that could inject additional properties. + */ + private function sanitizeCssValue(string $value): string + { + return preg_replace('/[;\{\}:]/', '', $value) ?? ''; + } + private function renderFontsPreview(array $row): string { // ... - $font = htmlspecialchars((string) $child['font'], ENT_QUOTES); - $weight = htmlspecialchars((string) $child['font_weight'], ENT_QUOTES); + $font = htmlspecialchars($this->sanitizeCssValue((string) $child['font']), ENT_QUOTES); + $weight = htmlspecialchars($this->sanitizeCssValue((string) $child['font_weight']), ENT_QUOTES);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/Preview/StyleguidePreviewRenderer.php` around lines 99 - 107, The inline CSS is built from unvalidated $font and $weight in StyleguidePreviewRenderer (variables $font, $weight, $label, $displayName, $style), which allows CSS injection; validate and sanitize before concatenation by applying a whitelist check: allow $font to match a safe regex (e.g. letters, digits, spaces, commas, hyphens, quotes and parentheses) or else replace with a safe default like "sans-serif", and allow $weight only if it matches numeric weights (100-900) or keywords (normal,bold,bolder,lighter) otherwise set to "normal"; after validation still pass through htmlspecialchars and then build $style from the validated values so only safe values are inserted into the inline CSS..ddev/.setup/scripts/utils.sh (1)
373-385: Extract shared post-setup mutations to avoid drift.
post_setup_11andpost_setup_12duplicate the samesedadjustments. Please move shared mutations into one helper with a version-specific config path argument.♻️ Minimal refactor sketch
+function apply_common_site_adjustments() { + local deprecations_file=$1 + sed -i "/'deprecations'/,/^[[:space:]]*'disabled' => true,/s/'disabled' => true,/'disabled' => false,/" "$deprecations_file" + sed -i -e "s/base: ht\//base: \//g" "/var/www/html/.Build/$VERSION/config/sites/main/config.yaml" + sed -i -e 's/base: \/en\//base: \//g' "/var/www/html/.Build/$VERSION/config/sites/main/config.yaml" +} + function post_setup_11 { $TYPO3_BIN install:setup -n --database-name $DATABASE setup_typo3 $TYPO3_BIN configuration:set 'GFX/processor_path_lzw' '/usr/bin/' - sed -i "/'deprecations'/,/^[[:space:]]*'disabled' => true,/s/'disabled' => true,/'disabled' => false,/" /var/www/html/.Build/$VERSION/public/typo3conf/LocalConfiguration.php - sed -i -e "s/base: ht\//base: \//g" /var/www/html/.Build/$VERSION/config/sites/main/config.yaml - sed -i -e 's/base: \/en\//base: \//g' /var/www/html/.Build/$VERSION/config/sites/main/config.yaml + apply_common_site_adjustments "/var/www/html/.Build/$VERSION/public/typo3conf/LocalConfiguration.php" }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.ddev/.setup/scripts/utils.sh around lines 373 - 385, post_setup_11 and post_setup_12 duplicate the same sed-based mutations; extract those shared sed calls into a new helper (e.g., apply_post_setup_mutations or post_setup_common) that accepts the version-specific config path (the LocalConfiguration.php and config/sites/main/config.yaml paths) and replace the inline sed lines in both post_setup_11 and post_setup_12 with a call to this helper, passing the appropriate /var/www/html/.Build/$VERSION/... paths so all shared edits are centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.ddev/.setup/scripts/utils.sh:
- Around line 163-165: post_setup() currently dispatches to post_setup_11 when
VERSION == "11" via the post_setup_11 symbol, but there is no corresponding
.ddev/commands/web/.install-11 entrypoint; either add that missing .install-11
script in .ddev/commands/web/ implementing whatever post_setup_11 expects, or
remove the VERSION == "11" branch and delete/rename post_setup_11 to avoid
calling a non-existent dispatcher; update any references to post_setup_11 to
match the chosen approach so ddev install 11 no longer fails.
---
Nitpick comments:
In @.ddev/.setup/scripts/utils.sh:
- Around line 373-385: post_setup_11 and post_setup_12 duplicate the same
sed-based mutations; extract those shared sed calls into a new helper (e.g.,
apply_post_setup_mutations or post_setup_common) that accepts the
version-specific config path (the LocalConfiguration.php and
config/sites/main/config.yaml paths) and replace the inline sed lines in both
post_setup_11 and post_setup_12 with a call to this helper, passing the
appropriate /var/www/html/.Build/$VERSION/... paths so all shared edits are
centralized.
In `@Classes/Preview/StyleguidePreviewRenderer.php`:
- Around line 99-107: The inline CSS is built from unvalidated $font and $weight
in StyleguidePreviewRenderer (variables $font, $weight, $label, $displayName,
$style), which allows CSS injection; validate and sanitize before concatenation
by applying a whitelist check: allow $font to match a safe regex (e.g. letters,
digits, spaces, commas, hyphens, quotes and parentheses) or else replace with a
safe default like "sans-serif", and allow $weight only if it matches numeric
weights (100-900) or keywords (normal,bold,bolder,lighter) otherwise set to
"normal"; after validation still pass through htmlspecialchars and then build
$style from the validated values so only safe values are inserted into the
inline CSS.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 42143e17-b1cc-4536-ba14-ea1f9e1697cd
⛔ Files ignored due to path filters (1)
composer.lockis excluded by!**/*.lock
📒 Files selected for processing (6)
.ddev/.setup/scripts/utils.sh.ddev/commands/web/.install-12Classes/Preview/StyleguidePreviewRenderer.phpREADME.mdResources/Private/Templates/Icons.htmlcomposer.json
🚧 Files skipped from review as they are similar to previous changes (3)
- Resources/Private/Templates/Icons.html
- README.md
- .ddev/commands/web/.install-12
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
Classes/Preview/StyleguidePreviewRenderer.php (1)
128-143: Filter icon candidates to image file types before counting/rendering.On Lines 128-143, every regular file is treated as an icon. Non-image files can consume the 20-item cap and produce broken thumbnails.
♻️ Proposed refinement
foreach ($files as $file) { if ('.' === $file || '..' === $file || !is_file($absDir.'/'.$file)) { continue; } + $extension = strtolower((string) pathinfo($file, PATHINFO_EXTENSION)); + if (!in_array($extension, ['svg', 'png', 'jpg', 'jpeg', 'gif', 'webp'], true)) { + continue; + } ++$count; if ($count > 20) { $hasMore = true;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Classes/Preview/StyleguidePreviewRenderer.php` around lines 128 - 143, The loop treating every regular file as an icon must skip non-image files before incrementing $count or pushing into $icons; update the foreach that iterates $files (using $absDir) to test each candidate is an image (e.g. check extension against a whitelist like jpg/jpeg/png/gif/svg or use getimagesize/finfo to confirm image MIME) and only then ++$count and append the array with 'name' and 'webPath' (keep using PathUtility::getAbsoluteWebPath($absDir.'/'.$file)); ensure the 20-item cap ($count > 20) applies only to validated image entries so non-image files do not consume the limit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Classes/Preview/StyleguidePreviewRenderer.php`:
- Around line 161-168: The webPath generation should only use
PathUtility::getAbsoluteWebPath when the resolved absolute path actually points
to a file; update the block that builds the $images[] entry (using $extPath and
$absPath) to guard creation of 'webPath' with is_file($absPath) instead of just
checking that $absPath is non-empty, so missing files will yield an empty
webPath and the template can fall back to {image.path}.
---
Nitpick comments:
In `@Classes/Preview/StyleguidePreviewRenderer.php`:
- Around line 128-143: The loop treating every regular file as an icon must skip
non-image files before incrementing $count or pushing into $icons; update the
foreach that iterates $files (using $absDir) to test each candidate is an image
(e.g. check extension against a whitelist like jpg/jpeg/png/gif/svg or use
getimagesize/finfo to confirm image MIME) and only then ++$count and append the
array with 'name' and 'webPath' (keep using
PathUtility::getAbsoluteWebPath($absDir.'/'.$file)); ensure the 20-item cap
($count > 20) applies only to validated image entries so non-image files do not
consume the limit.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f36d3afe-f221-49cd-bc25-c8bcaa12ab21
📒 Files selected for processing (8)
Classes/Preview/StyleguidePreviewRenderer.phpConfiguration/TsConfig/TCEFORM.tsconfigResources/Private/Templates/Preview/Colors.htmlResources/Private/Templates/Preview/Fonts.htmlResources/Private/Templates/Preview/Icons.htmlResources/Private/Templates/Preview/Images.htmlcomposer-unused.phpcomposer.json
🚧 Files skipped from review as they are similar to previous changes (1)
- composer.json
…→ typo3styleguide)
# Conflicts: # composer.json # composer.lock
Fixes #29 & #30
Summary
bw-static-templatedependency with native IRRE content elements (Colors, Fonts, Icons, Images)Breaking Changes
bw-static-templateis no longer a hard dependency (moved tosuggest)Patterns/Colors.html,Patterns/Templates.html, etc.) are replaced by dedicated content elements with IRRE child recordsRender\TemplateViewHelperhas been removedtx_metypo3styleguide_color,tx_metypo3styleguide_font,tx_metypo3styleguide_imageChanges
Classes/Preview/StyleguidePreviewRenderer.php— New backend preview with color swatches, font specimens, icon/image thumbnailsClasses/ViewHelpers/*.php— Converted fromrenderStatic()torender()for Fluid v4 compatibilityClasses/ViewHelpers/Uri/ResourcePathViewHelper.php— New ViewHelper for resolving EXT: pathsConfiguration/TCA/tx_metypo3styleguide_*.php— New TCA for color, font, image child recordsConfiguration/TCA/Overrides/tt_content.php— Register 4 new CTypes with IRRE fields and custom iconsConfiguration/TsConfig/ContentElements/*.tsconfig— Dedicated Styleguide wizard tabConfiguration/TsConfig/TCEFORM.tsconfig— Restrict styleguide CEs to styleguide page typeResources/Private/Templates/*.html— Frontend templates for new content elementsResources/Public/Icons/content-styleguide-*.svg— Custom content element iconscomposer.json— Add TYPO3 v14, Fluid v4/v5 support; movebw-static-templateto suggestSummary by CodeRabbit
New Features
Changed
Documentation