@elenajs/plugin-rollup-css 0.5.0 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +57 -8
  2. package/package.json +10 -2
  3. package/src/index.js +71 -7
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  <div align="center">
2
2
  <picture>
3
- <source media="(prefers-color-scheme: dark)" srcset="https://elenajs.com/img/elena-dark.png" alt="Elena" width="201" height="230">
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://elenajs.com/img/elena-dark.png" alt="Elena" width="558" height="220">
4
4
  </source>
5
- <source media="(prefers-color-scheme: light)" srcset="https://elenajs.com/img/elena.png" alt="Elena" width="201" height="230">
5
+ <source media="(prefers-color-scheme: light)" srcset="https://elenajs.com/img/elena-light.png" alt="Elena" width="558" height="220">
6
6
  </source>
7
- <img src="https://elenajs.com/img/elena.png" alt="Elena" width="201" height="230">
7
+ <img src="https://elenajs.com/img/elena-light.png" alt="Elena" width="558" height="220">
8
8
  </picture>
9
9
 
10
10
  ### Rollup plugin that minifies and bundles individual Elena CSS files.
@@ -30,10 +30,14 @@
30
30
  - **[Usage](#usage)**
31
31
  - **[Individual CSS files](#individual-css-files)**
32
32
  - **[CSS bundle](#css-bundle)**
33
- - **[Both together](#both-together)**
33
+ - **[CSS Module Scripts](#css-module-scripts)**
34
+ - **[Static styles](#static-styles)**
35
+ - **[All together](#all-together)**
34
36
  - **[API](#api)**
35
37
  - **[`cssPlugin(srcDir)`](#csspluginsrcdir)**
36
38
  - **[`cssBundlePlugin(srcDir, fileName)`](#cssbundlepluginsrcdir-filename)**
39
+ - **[`cssModuleScriptPlugin()`](#cssmodulescriptplugin)**
40
+ - **[`cssStaticStylesPlugin()`](#cssstaticstylesplugin)**
37
41
  - **[`minifyCss(css, filename?)`](#minifycsscss-filename)**
38
42
 
39
43
  ## Install
@@ -78,18 +82,55 @@ export default {
78
82
  };
79
83
  ```
80
84
 
81
- ### Both together
85
+ ### CSS Module Scripts
82
86
 
83
- Use both plugins to emit individual files and a concatenated bundle:
87
+ Handle `import styles from "./component.css" with { type: "css" }` imports. The plugin intercepts these imports, minifies the CSS, and returns a JS module that constructs a `CSSStyleSheet` for Shadow DOM adoption. CSS files handled this way are automatically excluded from `cssBundlePlugin`:
84
88
 
85
89
  ```js
86
90
  // rollup.config.js
87
- import { cssPlugin, cssBundlePlugin } from "@elenajs/plugin-rollup-css";
91
+ import { cssModuleScriptPlugin } from "@elenajs/plugin-rollup-css";
92
+
93
+ export default {
94
+ input: "src/index.js",
95
+ output: { dir: "dist", format: "esm" },
96
+ plugins: [cssModuleScriptPlugin()],
97
+ };
98
+ ```
99
+
100
+ ### Static styles
101
+
102
+ Minify CSS strings assigned to `static styles` template literal class fields:
103
+
104
+ ```js
105
+ // rollup.config.js
106
+ import { cssStaticStylesPlugin } from "@elenajs/plugin-rollup-css";
107
+
108
+ export default {
109
+ input: "src/index.js",
110
+ output: { dir: "dist", format: "esm" },
111
+ plugins: [cssStaticStylesPlugin()],
112
+ };
113
+ ```
114
+
115
+ ### All together
116
+
117
+ Use all plugins together for a complete CSS build pipeline:
118
+
119
+ ```js
120
+ // rollup.config.js
121
+ import {
122
+ cssPlugin,
123
+ cssBundlePlugin,
124
+ cssModuleScriptPlugin,
125
+ cssStaticStylesPlugin,
126
+ } from "@elenajs/plugin-rollup-css";
88
127
 
89
128
  export default {
90
129
  input: "src/index.js",
91
130
  output: { dir: "dist", format: "esm" },
92
131
  plugins: [
132
+ cssModuleScriptPlugin(),
133
+ cssStaticStylesPlugin(),
93
134
  cssPlugin("src"),
94
135
  cssBundlePlugin("src", "bundle.css"),
95
136
  ],
@@ -108,13 +149,21 @@ Returns a Rollup plugin that finds all `.css` files in `srcDir` and emits each o
108
149
 
109
150
  ### `cssBundlePlugin(srcDir, fileName)`
110
151
 
111
- Returns a Rollup plugin that concatenates all `.css` files in `srcDir`, minifies the result, and emits it as a single asset.
152
+ Returns a Rollup plugin that concatenates all `.css` files in `srcDir`, minifies the result, and emits it as a single asset. CSS files resolved by `cssModuleScriptPlugin` are automatically excluded from the bundle.
112
153
 
113
154
  | Parameter | Type | Description |
114
155
  | ---------- | -------- | ----------------------------------------------------- |
115
156
  | `srcDir` | `string` | Source directory to scan for `.css` files. |
116
157
  | `fileName` | `string` | Output filename for the bundle (e.g. `"bundle.css"`). |
117
158
 
159
+ ### `cssModuleScriptPlugin()`
160
+
161
+ Returns a Rollup plugin that handles CSS Module Script imports (`with { type: "css" }`). Reads the CSS file, minifies it, and returns a JS module that constructs and exports a `CSSStyleSheet` for Shadow DOM adoption. Must be listed before `@rollup/plugin-node-resolve` in the plugins array.
162
+
163
+ ### `cssStaticStylesPlugin()`
164
+
165
+ Returns a Rollup plugin that finds `static styles` class fields with template literal values and minifies the CSS inside them.
166
+
118
167
  ### `minifyCss(css, filename?)`
119
168
 
120
169
  Minifies a CSS string using [Lightning CSS](https://lightningcss.dev/).
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "@elenajs/plugin-rollup-css",
3
- "version": "0.5.0",
3
+ "version": "1.0.0-beta.1",
4
4
  "description": "Rollup plugin that minifies individual CSS files and optionally concatenates them into a single bundle.",
5
5
  "author": "Elena <hi@elenajs.com>",
6
6
  "homepage": "https://elenajs.com/",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/getelena/elena.git",
10
+ "directory": "packages/plugin-rollup-css"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/getelena/elena/issues"
14
+ },
7
15
  "license": "MIT",
8
16
  "publishConfig": {
9
17
  "access": "public"
@@ -30,5 +38,5 @@
30
38
  "devDependencies": {
31
39
  "vitest": "4.0.18"
32
40
  },
33
- "gitHead": "c181af0625f691a95a5cb1ef9adb0d7f2c796eae"
41
+ "gitHead": "66d1e66dd467c20d7c5c70ffcb5678c6a2694690"
34
42
  }
package/src/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * ██████████ ████
3
3
  * ░░███░░░░░█░░███
4
- * ░███ █ ░ ███ ██████ ████████ ██████
5
- * ░██████ ███ ███░░███░░███░░███ ░░░░░███
6
- * ░███░░█ ███ ░███████ ░███ ░███ ███████
7
- * ░███ ░ █ ███ ░███░░░ ░███ ░███ ███░░███
4
+ * ░███ █ ░ ░███ ██████ ████████ ██████
5
+ * ░██████ ░███ ███░░███░░███░░███ ░░░░░███
6
+ * ░███░░█ ░███ ░███████ ░███ ░███ ███████
7
+ * ░███ ░ █ ░███ ░███░░░ ░███ ░███ ███░░███
8
8
  * ██████████ █████░░██████ ████ █████░░████████
9
9
  * ░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░░░
10
10
  *
@@ -12,7 +12,7 @@
12
12
  * https://elenajs.com
13
13
  */
14
14
 
15
- import { basename } from "path";
15
+ import { basename, resolve, dirname } from "path";
16
16
  import { readFileSync, readdirSync } from "fs";
17
17
  import { transform } from "lightningcss";
18
18
 
@@ -23,7 +23,7 @@ import { transform } from "lightningcss";
23
23
  * @param {string} [filename]
24
24
  * @returns {string}
25
25
  */
26
- function minifyCss(css, filename = "style.css") {
26
+ export function minifyCss(css, filename = "style.css") {
27
27
  const { code } = transform({
28
28
  filename,
29
29
  code: Buffer.from(css),
@@ -32,6 +32,59 @@ function minifyCss(css, filename = "style.css") {
32
32
  return code.toString();
33
33
  }
34
34
 
35
+ /**
36
+ * Rollup plugin that handles CSS Module Script imports (`with { type: "css" }`).
37
+ * Loads the CSS file content, minifies it, and returns a JS module that
38
+ * constructs and exports a CSSStyleSheet for Shadow DOM adoption. This prevents
39
+ * Rollup from attempting to parse CSS files as JavaScript.
40
+ *
41
+ * @returns {import("rollup").Plugin}
42
+ */
43
+ export function cssModuleScriptPlugin() {
44
+ const PREFIX = "\0css-module:";
45
+
46
+ return {
47
+ name: "css-module-script",
48
+ resolveId(source, importer, options) {
49
+ if (!source.endsWith(".css") || options?.attributes?.type !== "css") {
50
+ return null;
51
+ }
52
+ return { id: PREFIX + resolve(dirname(importer), source) };
53
+ },
54
+ load(id) {
55
+ if (!id.startsWith(PREFIX)) {
56
+ return null;
57
+ }
58
+ const filePath = id.slice(PREFIX.length);
59
+ const css = minifyCss(readFileSync(filePath, "utf8"), basename(filePath));
60
+ return `const sheet = new CSSStyleSheet();\nsheet.replaceSync(${JSON.stringify(css)});\nexport default sheet;`;
61
+ },
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Rollup plugin that minifies CSS strings assigned to `static styles` class fields.
67
+ *
68
+ * @returns {import("rollup").Plugin}
69
+ */
70
+ export function cssStaticStylesPlugin() {
71
+ return {
72
+ name: "css-static-styles",
73
+ transform(code, id) {
74
+ if (!id.endsWith(".js") && !id.endsWith(".ts")) {
75
+ return null;
76
+ }
77
+ if (!code.includes("static styles")) {
78
+ return null;
79
+ }
80
+ const newCode = code.replace(/static\s+styles\s*=\s*`([\s\S]*?)`/g, (_match, css) => {
81
+ return `static styles = \`${minifyCss(css)}\``;
82
+ });
83
+ return newCode !== code ? { code: newCode } : null;
84
+ },
85
+ };
86
+ }
87
+
35
88
  /**
36
89
  * Rollup plugin that copies and minifies individual CSS files from `srcDir`
37
90
  * into the output directory.
@@ -48,6 +101,9 @@ export function cssPlugin(srcDir) {
48
101
  .map(f => `${srcDir}/${f}`);
49
102
 
50
103
  for (const file of cssFiles) {
104
+ if (this.addWatchFile) {
105
+ this.addWatchFile(resolve(file));
106
+ }
51
107
  const source = minifyCss(readFileSync(file, "utf8"), basename(file));
52
108
  this.emitFile({ type: "asset", fileName: basename(file), source });
53
109
  }
@@ -67,9 +123,17 @@ export function cssBundlePlugin(srcDir, fileName) {
67
123
  return {
68
124
  name: "css-bundle",
69
125
  generateBundle() {
126
+ const shadowDomCssFiles = new Set();
127
+ for (const id of this.getModuleIds()) {
128
+ if (id.startsWith("\0css-module:")) {
129
+ shadowDomCssFiles.add(id.slice("\0css-module:".length));
130
+ }
131
+ }
132
+
70
133
  const cssFiles = readdirSync(srcDir, { recursive: true })
71
134
  .filter(f => f.endsWith(".css"))
72
- .map(f => `${srcDir}/${f}`);
135
+ .map(f => resolve(`${srcDir}/${f}`))
136
+ .filter(f => !shadowDomCssFiles.has(f));
73
137
 
74
138
  const source = minifyCss(cssFiles.map(f => readFileSync(f, "utf8")).join("\n"), fileName);
75
139