Skip to content

Commit 32d5edc

Browse files
feat: loader bridge for css module hashed class names. (#64)
1 parent 7b3b45c commit 32d5edc

22 files changed

Lines changed: 1848 additions & 76 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ node_modules/
33
dist/
44
dist-webpack/
55
dist-auto-stable/
6+
dist-bridge/
7+
dist-bridge-webpack/
68
coverage/
79
.c8/
810
.duel-cache/

.oxlintrc.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@
2020
"rules": {
2121
"no-shadow": "off",
2222
"@typescript-eslint/no-shadow": "error",
23+
"@typescript-eslint/no-unused-vars": [
24+
"error",
25+
{
26+
"argsIgnorePattern": "^_",
27+
"varsIgnorePattern": "^_",
28+
"ignoreRestSiblings": true
29+
}
30+
],
2331
"@typescript-eslint/no-explicit-any": "error",
2432
"unicorn/filename-case": [
2533
"error",

docs/loader.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,71 @@ Pass `autoStable` to duplicate every matching class selector with a deterministi
5757
- CSS Modules: exports and generated class strings include both the hashed class and the stable class so you can reference either at runtime.
5858
- `autoStable` forces a LightningCSS pass; use `include`/`exclude` to scope which class tokens are duplicated.
5959

60+
### Bridge loader (CSS Modules)
61+
62+
When you want `knightedCss` to reflect the **hashed class names produced by your existing
63+
CSS Modules pipeline**, use the companion loader `@knighted/css/loader-bridge`. It runs
64+
after your Sass/CSS modules loaders and simply wraps their output (no reprocessing).
65+
66+
```js
67+
// rspack.config.js or webpack.config.js
68+
export default {
69+
module: {
70+
rules: [
71+
{
72+
test: /\.module\.(css|scss|sass)$/,
73+
oneOf: [
74+
{
75+
resourceQuery: /knighted-css/,
76+
use: [
77+
{
78+
loader: '@knighted/css/loader-bridge',
79+
},
80+
{
81+
loader: 'css-loader',
82+
options: {
83+
exportType: 'string',
84+
modules: true,
85+
},
86+
},
87+
'sass-loader',
88+
],
89+
},
90+
{
91+
use: [
92+
{
93+
loader: 'css-loader',
94+
options: {
95+
modules: true,
96+
},
97+
},
98+
'sass-loader',
99+
],
100+
},
101+
],
102+
},
103+
],
104+
},
105+
}
106+
```
107+
108+
```ts
109+
import { knightedCss, knightedCssModules } from './card.module.scss?knighted-css'
110+
111+
// knightedCss uses the same hashed selectors as the DOM
112+
shadowRoot.adoptedStyleSheets[0].replaceSync(knightedCss)
113+
114+
// optional convenience mapping of the CSS module locals
115+
console.log(knightedCssModules)
116+
```
117+
118+
> [!NOTE]
119+
> The bridge loader does not generate `stableSelectors`. It simply re-exports the
120+
> upstream output and resolves `knightedCss` by calling the upstream module’s
121+
> `toString()` or using its default string export when present. For CSS Modules
122+
> pipelines, configure the `?knighted-css` branch to emit a string (for example,
123+
> `css-loader` with `exportType: 'string'`) so `knightedCss` is populated.
124+
60125
### Combined imports
61126

62127
Need the component exports **and** the compiled CSS from a single import? Use `?knighted-css&combined` and narrow the result with `KnightedCssCombinedModule` to keep TypeScript happy:

0 commit comments

Comments
 (0)