Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@

## Features

- Traverses module graphs using [`dependency-tree`](https://github.com/dependents/node-dependency-tree) to find transitive style imports.
- Traverses module graphs with a built-in walker to find transitive style imports (no bundler required).
- Resolution parity via [`oxc-resolver`](https://github.com/oxc-project/oxc-resolver): tsconfig `paths`, package `exports` conditions, and extension aliasing (e.g., `.css.js` → `.css.ts`) are honored without wiring up a bundler.
- Compiles `*.css`, `*.scss`, `*.sass`, `*.less`, and `*.css.ts` (vanilla-extract) files out of the box.
- Optional post-processing via [`lightningcss`](https://github.com/parcel-bundler/lightningcss) for minification, prefixing, media query optimizations, or specificity boosts.
- Pluggable resolver/filter hooks for custom module resolution (e.g., Rspack/Vite/webpack aliases) or selective inclusion.
- First-class loader (`@knighted/css/loader`) so bundlers can import compiled CSS alongside their modules via `?knighted-css`.

## Requirements

- Node.js `>= 22.15.0`
- Node.js `>= 22.17.0`
- npm `>= 10.9.0`
- Install peer toolchains you intend to use (`sass`, `less`, `@vanilla-extract/integration`, etc.).

Expand Down Expand Up @@ -66,10 +67,10 @@ type CssOptions = {
strategy?: SpecificityStrategy
match?: SpecificitySelector[]
}
dependencyTree?: DependencyTreeOptions
moduleGraph?: ModuleGraphOptions
resolver?: (
specifier: string,
ctx: { cwd: string },
ctx: { cwd: string; from?: string },
) => string | Promise<string | undefined>
peerResolver?: (name: string) => Promise<unknown> // for custom module loading
}
Expand All @@ -81,6 +82,7 @@ Typical customizations:

- **filter** – Skip certain paths (e.g., storybook-only styles) before compilation.
- **resolver** – Resolve virtual specifiers the way your bundler does (the repo ships test fixtures for webpack, Vite, and Rspack).
- **moduleGraph** – Configure tsconfig path aliases, extra script extensions, or custom `package.json` conditions for the built-in dependency walker.
- **lightningcss** – Pass `true` for defaults or a config object for minification/autoprefixing.
- **specificityBoost** – Provide a Lightning CSS visitor to bump specificity on selected selectors (e.g., duplicate a class for matching selectors).

Expand Down Expand Up @@ -388,7 +390,7 @@ That hint keeps the upstream CommonJS helpers intact while still letting the res

### Custom resolver (enhanced-resolve example)

If your project uses aliases or nonstandard resolution, plug in a custom resolver. Here’s how to use [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve):
The built-in walker already leans on [`oxc-resolver`](https://github.com/oxc-project/oxc-resolver), so tsconfig `paths`, package `exports` conditions, and common extension aliases work out of the box. If you still need to mirror bespoke behavior (virtual modules, framework-specific loaders, etc.), plug in a custom resolver. Here’s how to use [`enhanced-resolve`](https://github.com/webpack/enhanced-resolve):

```ts
import { ResolverFactory } from 'enhanced-resolve'
Expand Down
5 changes: 3 additions & 2 deletions docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Overview

- The loader walks the module graph and gathers style-producing files (`.css`, `.scss`, `.sass`, `.less`, `.css.ts`, etc.).
- It uses `dependency-tree` (via `precinct`) to follow imports in the order they appear in source.
- It walks the module graph with a built-in depth-first resolver so imports are visited in source order.
- Resolution is powered by [`oxc-resolver`](https://github.com/oxc-project/oxc-resolver), so tsconfig `paths`, package `exports` conditions, and extension aliasing (like `.css.js` → `.css.ts`) all map to the same targets you’d get in a bundler.
- CSS from those files is concatenated in that discovery order and returned as `knightedCss` for injection (e.g., Lit ` css`` `, SSR, SSG).
- We do **not** sort or reorder; first-seen order is kept, so the CSS cascade mirrors the original import sequence.

Expand All @@ -16,7 +17,7 @@

### Example ordering

We rely on `dependency-tree` (via `precinct`) to follow imports in the order they appear in source. We concatenate CSS in depth-first, preorder (parent before children), preserving sibling order as written. Files are deduped: the first time a file is seen, it’s included; later encounters are skipped to avoid reshuffling the cascade. We never sort the list, and `lightningcss` preserves the rule order we provide.
The walker performs a depth-first, preorder traversal (parent before children) so imports are resolved exactly as they are written in source. Files are deduped: the first time a file is seen, it’s included; later encounters are skipped to avoid reshuffling the cascade. We never sort the list, and `lightningcss` preserves the rule order we provide.

Given:

Expand Down
Loading