Skip to content

feat(vite): add vite support#70

Merged
bennypowers merged 6 commits intomainfrom
feat/vite
Mar 1, 2026
Merged

feat(vite): add vite support#70
bennypowers merged 6 commits intomainfrom
feat/vite

Conversation

@bennypowers
Copy link
Copy Markdown
Owner

@bennypowers bennypowers commented Nov 3, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new Vite plugin for importing CSS files as Lit's tagged template literals, enabling CSS-in-JS workflows in Vite projects with support for CSS preprocessors (Sass, PostCSS, Less, Stylus) and Hot Module Replacement.
  • Documentation

    • Added comprehensive plugin documentation including usage examples, configuration options, and integration test guide.
  • Tests

    • Added integration tests and test fixtures to verify plugin functionality across various CSS processing scenarios.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Nov 3, 2025

🦋 Changeset detected

Latest commit: 45991d3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
vite-plugin-lit-css Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@bennypowers
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 3, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 3, 2025

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc8320c and 45991d3.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (1)
  • README.md

📝 Walkthrough

Walkthrough

A new Vite plugin package (vite-plugin-lit-css) is introduced, enabling CSS file imports as Lit template literals. The PR includes the plugin implementation, documentation, integration tests with a sample LitElement component, unit test fixtures covering various CSS preprocessors, and updates to the root README.

Changes

Cohort / File(s) Summary
Root Documentation
README.md
Reorganizes package list to add vite-plugin-lit-css entries and adjust positioning of related tools (Webpack, TypeScript entries).
Plugin Implementation
packages/vite-plugin-lit-css/vite-plugin-lit-css.ts
Core Vite plugin that intercepts CSS imports, uses resolveId to map them to virtual modules, and applies the lit-css transform to produce JS with Lit's css template literal.
Package Metadata
packages/vite-plugin-lit-css/package.json, packages/vite-plugin-lit-css/CHANGELOG.md
Defines package manifest with dependencies on @pwrs/lit-css and @rollup/pluginutils, peer dependency on multiple Vite versions; documents version 1.0.0 release with HMR, transform, and minification support.
Plugin Documentation
packages/vite-plugin-lit-css/README.md
Comprehensive guide covering installation, usage examples (basic, FAST, Sass/PostCSS), configuration options, HMR behavior, and related plugins.
Integration Test Suite
packages/vite-plugin-lit-css/integration-test/package.json, packages/vite-plugin-lit-css/integration-test/vite.config.js, packages/vite-plugin-lit-css/integration-test/index.html, packages/vite-plugin-lit-css/integration-test/src/my-element.js, packages/vite-plugin-lit-css/integration-test/src/styles.css, packages/vite-plugin-lit-css/integration-test/README.md
Full integration test setup with a LitElement component that imports CSS, Vite configuration, test HTML, and documentation explaining the test approach.
Unit Test Fixtures
packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js, packages/vite-plugin-lit-css/test/expected/bare/output.js, packages/vite-plugin-lit-css/test/expected/basic/output.js, packages/vite-plugin-lit-css/test/expected/basic/boop.js, packages/vite-plugin-lit-css/test/expected/basic/fast.js, packages/vite-plugin-lit-css/test/expected/basic/uglified.js, packages/vite-plugin-lit-css/test/expected/postcss/output.js, packages/vite-plugin-lit-css/test/expected/scss/output.js, packages/vite-plugin-lit-css/test/expected/special-chars/output.js
Test harness that builds fixtures with the plugin and validates output; expected files demonstrate correct transformation across bare imports, custom transforms (boop, FAST), minification, PostCSS, Sass, and special character handling.
Changeset
.changeset/vite-plugin-lit-css.md
Release notes summarizing the new Vite plugin's capabilities: CSS-as-JS workflow, virtual module support, preprocessor compatibility, and integration with @pwrs/lit-css.

Sequence Diagram

sequenceDiagram
    participant User as Developer
    participant Vite
    participant VitePlugin as vite-plugin-lit-css
    participant LitCSS as `@pwrs/lit-css`
    participant Bundle

    User->>Vite: import styles from './styles.css'
    Vite->>VitePlugin: resolveId(moduleId)
    VitePlugin->>VitePlugin: Check filter match
    VitePlugin-->>Vite: Return virtual module ID<br/>(e.g., styles.css.lit-css.js)
    Vite->>VitePlugin: load(virtualModuleId)
    VitePlugin->>VitePlugin: Read original CSS file
    VitePlugin->>LitCSS: transform(css, options)
    LitCSS-->>VitePlugin: return JS with css template literal
    VitePlugin-->>Vite: JavaScript code with<br/>import {css} from 'lit'<br/>export const styles = css`...`
    Vite->>Bundle: Include transformed JS
    Bundle-->>User: Bundled output with<br/>Lit CSS in JS
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • feat(esbuild): inline #73: Modifies the @pwrs/lit-css transform API (toTaggedTemplateLiteral) that this PR's vite-plugin-lit-css calls, making it a direct code-level dependency.

Poem

🐰 A Vite plugin hops into the light,
CSS becomes templates, oh what a delight!
Bundled with Lit, they dance hand-in-paw,
Transform and resolve with nary a flaw! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(vite): add vite support' directly and clearly describes the main change: adding Vite plugin support to the lit-css package. The changeset introduces a complete vite-plugin-lit-css package with plugin implementation, integration tests, documentation, and changelog entries, which aligns perfectly with the title's intent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/vite

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.

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: 5

🧹 Nitpick comments (3)
packages/vite-plugin-lit-css/CHANGELOG.md (1)

3-3: Consider adding a release date to the version header.

Following "Keep a Changelog" conventions, include the release date in the format [1.0.0] - YYYY-MM-DD to provide clarity on when this version was released. This is particularly useful for tracking release timelines and is a common practice across many open-source projects.

Example:

-## 1.0.0
+## [1.0.0] - 2025-11-03
packages/vite-plugin-lit-css/README.md (1)

1-170: Excellent documentation!

The README is comprehensive and well-structured, covering installation, configuration, usage examples for multiple scenarios (Lit, FAST, Sass, PostCSS), and includes helpful notes about HMR and how the plugin works.

If you'd like to address the style suggestion from the linter, consider this minor change:

-This plugin works seamlessly with Vite's HMR. When you modify a CSS file, Vite will automatically reload the module and update your component styles without a full page refresh.
+This plugin works seamlessly with Vite's HMR. When you modify a CSS file, Vite will automatically reload the module and update your component styles without a full-page refresh.
packages/vite-plugin-lit-css/vite-plugin-lit-css.ts (1)

41-70: Robust resolveId implementation with good delegation pattern.

The implementation correctly:

  • Performs early returns for non-applicable cases
  • Delegates to other plugins via this.resolve with skipSelf
  • Uses the filter on the resolved path (not the raw import)
  • Returns a virtual module ID with the \0 prefix convention

The static analysis warning about string concatenation on line 66 is a false positive—this is the standard Rollup convention for virtual modules.

You may optionally address the linter's formatting suggestions:

       const resolution = await this.resolve(source, importer, {
-        skipSelf: true,  // Don't call ourselves recursively
+        skipSelf: true, // Don't call ourselves recursively
         ...options,
       });
       if (!source.endsWith('.css') && !source.endsWith('.scss') && !source.endsWith('.sass') &&
-          !source.endsWith('.less') && !source.endsWith('.styl')) {
+          !source.endsWith('.less') && !source.endsWith('.styl'))
         return null;
-      }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c69d07 and 6f7f563.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • packages/vite-plugin-lit-css/integration-test/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (20)
  • README.md (1 hunks)
  • packages/vite-plugin-lit-css/CHANGELOG.md (1 hunks)
  • packages/vite-plugin-lit-css/README.md (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/README.md (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/index.html (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/package.json (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/src/my-element.js (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/src/styles.css (1 hunks)
  • packages/vite-plugin-lit-css/integration-test/vite.config.js (1 hunks)
  • packages/vite-plugin-lit-css/package.json (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/bare/output.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/basic/boop.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/basic/fast.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/basic/output.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/basic/uglified.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/postcss/output.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/scss/output.js (1 hunks)
  • packages/vite-plugin-lit-css/test/expected/special-chars/output.js (1 hunks)
  • packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js (1 hunks)
  • packages/vite-plugin-lit-css/vite-plugin-lit-css.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Verify PR
packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js

[warning] 2-2: eslint: 'aliasPlugin' is defined but never used. (no-unused-vars). Command: eslint .


[error] 55-55: eslint: Unnecessary { after 'if' condition. (curly). Command: eslint .

packages/vite-plugin-lit-css/integration-test/src/my-element.js

[error] 5-5: eslint: Parsing error: Unexpected token =. Command: eslint .

🪛 GitHub Check: verify
packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js

[failure] 61-61:
Unnecessary { after 'if' condition


[failure] 55-55:
Unnecessary { after 'if' condition


[warning] 2-2:
'aliasPlugin' is defined but never used

packages/vite-plugin-lit-css/vite-plugin-lit-css.ts

[warning] 86-86:
Unexpected any. Specify a different type


[failure] 66-66:
Unexpected string concatenation


[failure] 55-55:
Multiple spaces found before '// Don't call ...'


[failure] 48-48:
Unnecessary { after 'if' condition

🪛 LanguageTool
packages/vite-plugin-lit-css/README.md

[uncategorized] ~155-~155: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ... update your component styles without a full page refresh. ## How It Works This plugin ...

(EN_COMPOUND_ADJECTIVE_INTERNAL)

🔇 Additional comments (22)
README.md (1)

30-30: LGTM!

The addition of Vite to the supported tools list is consistent with the existing format and correctly links to the new package directory.

packages/vite-plugin-lit-css/test/expected/basic/uglified.js (1)

1-5: LGTM!

This test fixture correctly demonstrates the expected output for minified CSS transformation, with proper dual export pattern (default and named).

packages/vite-plugin-lit-css/test/expected/basic/fast.js (1)

1-8: LGTM!

This test fixture correctly demonstrates the expected output for FAST element integration, importing from the correct package and using the standard export pattern.

packages/vite-plugin-lit-css/test/expected/basic/boop.js (1)

1-8: LGTM!

This test fixture correctly validates the custom specifier and tag functionality, demonstrating that the plugin can work with arbitrary template tag functions beyond just css from lit.

packages/vite-plugin-lit-css/package.json (1)

1-40: LGTM!

The package manifest is well-configured with:

  • Proper dual package support (ESM + CJS) via the exports field
  • Appropriate peer dependency range covering Vite 4.x, 5.x, and 6.x
  • Correct dependencies for the plugin functionality
  • Properly scoped files array for publication
packages/vite-plugin-lit-css/vite-plugin-lit-css.ts (3)

8-18: LGTM!

The LitCSSOptions interface is well-defined with clear JSDoc comments and appropriate type constraints.


26-40: LGTM!

The plugin initialization logic correctly destructures options with sensible defaults and creates a Rollup filter for file matching. The enforce: 'pre' configuration appropriately prioritizes this plugin before Vite's built-in CSS handling.


93-93: LGTM!

The default export provides convenient import syntax while the named export remains available for explicit imports.

packages/vite-plugin-lit-css/integration-test/vite.config.js (1)

1-18: LGTM!

The integration test configuration is well-structured:

  • Correctly imports the plugin from the parent directory
  • Uses library build mode appropriate for testing a component
  • Properly externalizes lit to avoid bundling peer dependencies
packages/vite-plugin-lit-css/integration-test/src/styles.css (1)

1-9: LGTM! Clean test fixture.

The CSS is simple and appropriate for integration testing. The hotpink color provides clear visual verification that the plugin is working correctly.

packages/vite-plugin-lit-css/test/expected/scss/output.js (1)

1-5: LGTM! Consistent test fixture pattern.

The expected output follows the standard pattern used across all test fixtures in this PR.

packages/vite-plugin-lit-css/test/expected/basic/output.js (1)

1-8: LGTM! Consistent test fixture pattern.

The expected output follows the standard pattern used across all test fixtures in this PR.

packages/vite-plugin-lit-css/test/expected/bare/output.js (1)

1-8: LGTM! Consistent test fixture pattern.

The expected output follows the standard pattern used across all test fixtures in this PR.

packages/vite-plugin-lit-css/integration-test/index.html (1)

1-16: LGTM! Well-structured integration test page.

The HTML provides a clear test harness with visual verification instructions. The structure is appropriate for Vite dev server testing.

packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js (1)

15-18: LGTM! Good type-checking practice.

The type check for the plugin configuration is a nice touch to ensure TypeScript types are correct.

packages/vite-plugin-lit-css/test/expected/postcss/output.js (1)

1-5: LGTM! Consistent test fixture pattern.

The expected output follows the standard pattern used across all test fixtures in this PR. The concatenated CSS rules appropriately demonstrate PostCSS processing.

packages/vite-plugin-lit-css/integration-test/README.md (1)

1-40: LGTM! Excellent documentation.

The README provides comprehensive guidance on the integration test purpose, usage, and verification steps. The rationale for having integration tests alongside unit tests is particularly valuable.

packages/vite-plugin-lit-css/integration-test/src/my-element.js (3)

7-12: LGTM!

The render method is correctly implemented and provides clear visual feedback for integration testing.


15-15: LGTM!

The custom element registration follows web components best practices with a properly formatted kebab-case name.


1-2: Verify the CSS import transformation.

The component imports styles from a CSS file without importing css from 'lit'. The plugin should transform the CSS import to return a properly wrapped Lit css template literal. Ensure the plugin handles this transformation correctly in both dev and build modes.

Run the following script to verify the plugin transformation:

packages/vite-plugin-lit-css/integration-test/package.json (1)

1-15: LGTM!

The package manifest is well-structured for an integration test with appropriate dependencies and scripts. The version ranges for lit (^3.0.0) and vite (^5.0.0) are current, and marking the package as private is correct.

packages/vite-plugin-lit-css/test/expected/special-chars/output.js (1)

1-11: LGTM!

This test fixture correctly demonstrates the expected plugin output for special character handling (including the emoji in the comment) and validates the dual export pattern that supports both default and named imports.

Comment thread packages/vite-plugin-lit-css/integration-test/src/my-element.js
Comment thread packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js Outdated
Comment thread packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js Outdated
Comment thread packages/vite-plugin-lit-css/test/vite-plugin-lit-css.test.js Outdated
Comment thread packages/vite-plugin-lit-css/vite-plugin-lit-css.ts
@bennypowers bennypowers merged commit 3bfb9ee into main Mar 1, 2026
2 checks passed
@bennypowers bennypowers deleted the feat/vite branch March 1, 2026 11:19
This was referenced Mar 1, 2026
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.

1 participant