Skip to content

Added support for returning vite assets in their correct group#1481

Open
jaxwilko wants to merge 4 commits intodevelopfrom
wip/add-vite-assets-twig-support
Open

Added support for returning vite assets in their correct group#1481
jaxwilko wants to merge 4 commits intodevelopfrom
wip/add-vite-assets-twig-support

Conversation

@jaxwilko
Copy link
Copy Markdown
Member

@jaxwilko jaxwilko commented May 6, 2026

This PR adds support for returning vite assets in their correct groups.

This is done so that CSS/JS added via ->addVite() is correctly rendered via the {% styles %} & {% scripts %} tags.

The getAssetType() method is a little fluffy as it will probably be extended later.

Summary by CodeRabbit

  • Refactor

    • Enhanced asset handling with tighter Vite integration: CSS and JS entrypoints are correctly grouped and emitted to prevent cross-leakage between styles and scripts; styles now emit the appropriate CSS entrypoints alongside Vite-managed assets.
  • Tests

    • Expanded test coverage for asset handling and Vite integration to verify CSS/JS emission, grouping behavior, and to guard against regressions.

@jaxwilko jaxwilko requested a review from damsfx May 6, 2026 20:42
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 64ac7dcf-8450-480a-bc63-497c6e5301a8

📥 Commits

Reviewing files that changed from the base of the PR and between e4fdeae and de1a9b4.

📒 Files selected for processing (1)
  • modules/system/tests/traits/AssetMakerTest.php
🚧 Files skipped from review as they are similar to previous changes (1)
  • modules/system/tests/traits/AssetMakerTest.php

Walkthrough

Replaces the assets function argument in modules/cms/twig/StylesNode.php from 'vite' to 'css'. Enhances modules/system/traits/AssetMaker.php to detect asset types (.css/.js), filter Vite bundle entrypoints by type, and emit Vite::tags for matching CSS and JS entrypoints; adds protected getAssetType(string $asset). Adds Vite-focused tests and helpers: modules/cms/tests/classes/TwigExtensionTest.php and modules/system/tests/traits/AssetMakerTest.php include fixture setup/teardown and multiple new unit tests validating CSS/JS and Vite integration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • wintercms/winter#1447: Directly related changes to StylesNode handling and AssetMaker Vite integration.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding support for returning Vite assets in their correct group (CSS vs JS), which enables proper rendering via Twig tags.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch wip/add-vite-assets-twig-support

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jaxwilko jaxwilko requested a review from LukeTowers May 6, 2026 20:42
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
modules/system/traits/AssetMaker.php (1)

76-86: ⚡ Quick win

Deduplicate the two Vite emission blocks.

The CSS and JS branches contain the same loop modulo the type literal. Extracting a small helper keeps makeAssets() readable and makes future tweaks (ordering, additional types, error handling) a one-place change. It also pairs naturally with the future-extensible intent called out for getAssetType() in the PR description.

♻️ Proposed extraction
         if ($type == null || $type == 'css') {
             foreach ($this->orderAssets($this->assets['css']) as $asset) {
                 ...
                 $result .= '<link' . $attributes . '>' . PHP_EOL;
             }
-
-            foreach ($this->assets['vite'] as $asset) {
-                $asset['attributes']['entrypoints'] = array_filter(
-                    $asset['attributes']['entrypoints'],
-                    fn ($entrypoint) => $this->getAssetType($entrypoint) === 'css'
-                );
-
-                if ($asset['attributes']['entrypoints']) {
-                    $result .= Vite::tags($asset['attributes']['entrypoints'], $asset['path']);
-                }
-            }
+            $result .= $this->makeViteAssetsForType('css');
         }
         ...
         if ($type == null || $type == 'js') {
             foreach ($this->orderAssets($this->assets['js']) as $asset) {
                 ...
                 $result .= '<script' . $attributes . '></script>' . PHP_EOL;
             }
-
-            foreach ($this->assets['vite'] as $asset) {
-                $asset['attributes']['entrypoints'] = array_filter(
-                    $asset['attributes']['entrypoints'],
-                    fn ($entrypoint) => $this->getAssetType($entrypoint) === 'js'
-                );
-
-                if ($asset['attributes']['entrypoints']) {
-                    $result .= Vite::tags($asset['attributes']['entrypoints'], $asset['path']);
-                }
-            }
+            $result .= $this->makeViteAssetsForType('js');
         }
protected function makeViteAssetsForType(string $type): string
{
    $result = '';
    foreach ($this->assets['vite'] as $asset) {
        $entrypoints = array_filter(
            $asset['attributes']['entrypoints'] ?? [],
            fn ($entrypoint) => $this->getAssetType($entrypoint) === $type
        );

        if ($entrypoints) {
            $result .= Vite::tags($entrypoints, $asset['path']);
        }
    }
    return $result;
}

Also applies to: 116-126

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/system/traits/AssetMaker.php` around lines 76 - 86, The two identical
loops over $this->assets['vite'] that filter entrypoints by type should be
extracted into a helper (e.g. protected function makeViteAssetsForType(string
$type): string) and the two inlined blocks in makeAssets() replaced with calls
to that helper for 'css' and 'js'; the helper should pull entrypoints via
$asset['attributes']['entrypoints'] ?? [], use array_filter with
$this->getAssetType($entrypoint) === $type, and call Vite::tags($entrypoints,
$asset['path']) when non-empty, returning the concatenated string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/system/traits/AssetMaker.php`:
- Around line 484-495: getAssetType currently returns only 'js' for .js and
'css' for .css, causing .ts/.tsx/.jsx/.mjs/.cjs/.vue and preprocessor styles
.scss/.sass to be dropped; update getAssetType(string $asset): ?string to also
treat .ts, .tsx, .jsx, .mjs, .cjs, .vue as 'js' and .scss, .sass (and keep .css)
as 'css' so makeAssets('js') and makeAssets('css') include typical Vite
entrypoints; while editing, keep the function name getAssetType and its return
semantics so existing callers (makeAssets, the Vite emission logic) continue to
work—optionally factor repeated Vite-emission filtering into a shared helper if
you want to remove duplication later.

---

Nitpick comments:
In `@modules/system/traits/AssetMaker.php`:
- Around line 76-86: The two identical loops over $this->assets['vite'] that
filter entrypoints by type should be extracted into a helper (e.g. protected
function makeViteAssetsForType(string $type): string) and the two inlined blocks
in makeAssets() replaced with calls to that helper for 'css' and 'js'; the
helper should pull entrypoints via $asset['attributes']['entrypoints'] ?? [],
use array_filter with $this->getAssetType($entrypoint) === $type, and call
Vite::tags($entrypoints, $asset['path']) when non-empty, returning the
concatenated string.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e53cd79b-1aef-488d-accb-4c14090e1d2b

📥 Commits

Reviewing files that changed from the base of the PR and between 0758670 and 4957bac.

📒 Files selected for processing (2)
  • modules/cms/twig/StylesNode.php
  • modules/system/traits/AssetMaker.php
💤 Files with no reviewable changes (1)
  • modules/cms/twig/StylesNode.php

Comment thread modules/system/traits/AssetMaker.php
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
modules/system/tests/traits/AssetMakerTest.php (2)

53-53: 💤 Low value

Naming nit: setUpViteFixture mimics a PHPUnit lifecycle hook.

setUp*-prefixed methods are typically auto-invoked PHPUnit hooks. Since this helper is called manually from each test, a name like prepareViteFixture() or bootViteFixture() would reduce reader surprise.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/system/tests/traits/AssetMakerTest.php` at line 53, The helper method
setUpViteFixture() should be renamed to avoid resembling PHPUnit lifecycle
hooks; rename the method (e.g., prepareViteFixture or bootViteFixture) and
update every test that calls setUpViteFixture to the new name, including any
references in AssetMakerTest and related fixtures or trait usages so the helper
remains manually-invoked and reader expectations are clear.

24-80: ⚡ Quick win

Consider extracting Vite fixture scaffolding into a shared trait.

These three constants, the entire tearDown() cleanup block, and the package-registration / hot-file portion of setUpViteFixture() are duplicated near-verbatim in modules/cms/tests/classes/TwigExtensionTest.php. Centralizing them into a shared test trait (e.g., System\Tests\Concerns\WithViteFixture) would keep cleanup in lockstep across both test files and avoid drift if the fixture path or hot URL ever changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/system/tests/traits/AssetMakerTest.php` around lines 24 - 80,
Duplicate Vite fixture scaffolding (constants VITE_FIXTURE_PACKAGE,
VITE_FIXTURE_THEME_PATH, VITE_HOT_URL, the tearDown() cleanup and the
package-registration/hot-file logic in setUpViteFixture()) exists in
AssetMakerTest and TwigExtensionTest; extract these into a shared test trait
(e.g., System\Tests\Concerns\WithViteFixture) that defines the three constants,
provides a protected tearDownViteFixture() or tearDown() implementation and a
setUpViteFixture() method containing the PackageManager registration and
hot-file creation, then have AssetMakerTest and TwigExtensionTest use that trait
and remove the duplicated constants and methods from those classes so both tests
share the single canonical implementation.
modules/cms/tests/classes/TwigExtensionTest.php (1)

15-31: ⚡ Quick win

Duplicated Vite fixture constants and tearDown — same root cause as in AssetMakerTest.

These constants and the tearDown() body match the ones in modules/system/tests/traits/AssetMakerTest.php. A shared trait would let both suites converge on a single cleanup implementation. (See the corresponding comment on AssetMakerTest.php.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/cms/tests/classes/TwigExtensionTest.php` around lines 15 - 31,
Extract the duplicated constants and cleanup logic into a shared trait (e.g.,
AssetFixtureCleanupTrait) that defines the constants VITE_FIXTURE_PACKAGE,
VITE_FIXTURE_THEME_PATH, VITE_HOT_URL and a protected method
cleanupViteFixtures() which contains the file/directory removal logic; then
update TwigExtensionTest::tearDown() and AssetMakerTest::tearDown() to call
$this->cleanupViteFixtures() before calling parent::tearDown(); ensure the trait
method is protected and referenced by the class tests so teardown behavior is
identical and duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@modules/cms/tests/classes/TwigExtensionTest.php`:
- Around line 15-31: Extract the duplicated constants and cleanup logic into a
shared trait (e.g., AssetFixtureCleanupTrait) that defines the constants
VITE_FIXTURE_PACKAGE, VITE_FIXTURE_THEME_PATH, VITE_HOT_URL and a protected
method cleanupViteFixtures() which contains the file/directory removal logic;
then update TwigExtensionTest::tearDown() and AssetMakerTest::tearDown() to call
$this->cleanupViteFixtures() before calling parent::tearDown(); ensure the trait
method is protected and referenced by the class tests so teardown behavior is
identical and duplication is removed.

In `@modules/system/tests/traits/AssetMakerTest.php`:
- Line 53: The helper method setUpViteFixture() should be renamed to avoid
resembling PHPUnit lifecycle hooks; rename the method (e.g., prepareViteFixture
or bootViteFixture) and update every test that calls setUpViteFixture to the new
name, including any references in AssetMakerTest and related fixtures or trait
usages so the helper remains manually-invoked and reader expectations are clear.
- Around line 24-80: Duplicate Vite fixture scaffolding (constants
VITE_FIXTURE_PACKAGE, VITE_FIXTURE_THEME_PATH, VITE_HOT_URL, the tearDown()
cleanup and the package-registration/hot-file logic in setUpViteFixture())
exists in AssetMakerTest and TwigExtensionTest; extract these into a shared test
trait (e.g., System\Tests\Concerns\WithViteFixture) that defines the three
constants, provides a protected tearDownViteFixture() or tearDown()
implementation and a setUpViteFixture() method containing the PackageManager
registration and hot-file creation, then have AssetMakerTest and
TwigExtensionTest use that trait and remove the duplicated constants and methods
from those classes so both tests share the single canonical implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 07d008b1-0323-427d-b35f-43563b53c25e

📥 Commits

Reviewing files that changed from the base of the PR and between 4957bac and 578ea0c.

📒 Files selected for processing (2)
  • modules/cms/tests/classes/TwigExtensionTest.php
  • modules/system/tests/traits/AssetMakerTest.php

Comment thread modules/system/tests/traits/AssetMakerTest.php Outdated
@damsfx
Copy link
Copy Markdown
Contributor

damsfx commented May 7, 2026

It works as expected for me. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants