ecij 0.1.1 → 0.3.0
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.
- package/README.md +55 -4
- package/dist/index.d.ts +14 -0
- package/dist/index.js +99 -119
- package/index.d.ts +1 -1
- package/package.json +17 -7
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# ecij
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/ecij)
|
|
4
|
+
[](https://github.com/nstepien/ecij/actions/workflows/ci.yml)
|
|
5
|
+
|
|
3
6
|
ecij (**E**xtract **C**SS-**i**n-**J**S) is a zero-runtime css-in-js plugin for [Rolldown](https://rolldown.rs/) and [Vite](https://vite.dev/).
|
|
4
7
|
|
|
5
8
|
It achieves this via static analysis by using [oxc-parser](https://www.npmjs.com/package/oxc-parser), as such it is limited to static expressions. The plugin will ignore dynamic or complex expressions.
|
|
@@ -8,7 +11,7 @@ The plugin does not process the CSS in any way whatsoever, it is merely output i
|
|
|
8
11
|
|
|
9
12
|
## Installation
|
|
10
13
|
|
|
11
|
-
```
|
|
14
|
+
```bash
|
|
12
15
|
npm install -D ecij
|
|
13
16
|
```
|
|
14
17
|
|
|
@@ -99,6 +102,20 @@ The `ecij()` plugin accepts an optional configuration object:
|
|
|
99
102
|
|
|
100
103
|
```ts
|
|
101
104
|
export interface Configuration {
|
|
105
|
+
/**
|
|
106
|
+
* Include patterns for files to process.
|
|
107
|
+
* Can be a string, RegExp, or array of strings/RegExp.
|
|
108
|
+
* @default /\.[cm]?[jt]sx?$/
|
|
109
|
+
*/
|
|
110
|
+
include?: string | RegExp | ReadonlyArray<string | RegExp>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Exclude patterns for files to skip.
|
|
114
|
+
* Can be a string, RegExp, or array of strings/RegExp.
|
|
115
|
+
* @default [/\/node_modules\//, /\.d\.ts$/]
|
|
116
|
+
*/
|
|
117
|
+
exclude?: string | RegExp | ReadonlyArray<string | RegExp>;
|
|
118
|
+
|
|
102
119
|
/**
|
|
103
120
|
* Prefix for generated CSS class names.
|
|
104
121
|
* Should not be empty, as generated hashes may start with a digit, resulting in invalid CSS class names.
|
|
@@ -116,11 +133,45 @@ ecij({
|
|
|
116
133
|
});
|
|
117
134
|
```
|
|
118
135
|
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
### Building
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npm run build
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Formatting
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run format
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Type Checking
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm run typecheck
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Running Tests
|
|
157
|
+
|
|
158
|
+
The project uses **integration tests** with **inline snapshot testing** to validate transformations.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Run tests once
|
|
162
|
+
npm test
|
|
163
|
+
|
|
164
|
+
# Run tests with coverage
|
|
165
|
+
npm run test:coverage
|
|
166
|
+
|
|
167
|
+
# Update inline snapshots after intentional changes
|
|
168
|
+
npm test -- -u
|
|
169
|
+
```
|
|
170
|
+
|
|
119
171
|
## TODO
|
|
120
172
|
|
|
121
|
-
-
|
|
122
|
-
- Support `include`/`exclude` configuration
|
|
173
|
+
- Log CSS extraction failures
|
|
123
174
|
- Scope handling
|
|
124
|
-
- Validate that the `css` used refers to
|
|
175
|
+
- Validate that the `css` used refers to the ecij export
|
|
125
176
|
- Full import/export handling (default/namespace import/export)
|
|
126
177
|
- Sourcemaps
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,18 @@ import { Plugin } from "rolldown";
|
|
|
2
2
|
|
|
3
3
|
//#region src/index.d.ts
|
|
4
4
|
interface Configuration {
|
|
5
|
+
/**
|
|
6
|
+
* Include patterns for files to process.
|
|
7
|
+
* Can be a string, RegExp, or array of strings/RegExp.
|
|
8
|
+
* @default /\.[cm]?[jt]sx?$/
|
|
9
|
+
*/
|
|
10
|
+
include?: string | RegExp | ReadonlyArray<string | RegExp>;
|
|
11
|
+
/**
|
|
12
|
+
* Exclude patterns for files to skip.
|
|
13
|
+
* Can be a string, RegExp, or array of strings/RegExp.
|
|
14
|
+
* @default [/\/node_modules\//, /\.d\.ts$/]
|
|
15
|
+
*/
|
|
16
|
+
exclude?: string | RegExp | ReadonlyArray<string | RegExp>;
|
|
5
17
|
/**
|
|
6
18
|
* Prefix for generated CSS class names.
|
|
7
19
|
* Should not be empty, as generated hashes may start with a digit, resulting in invalid CSS class names.
|
|
@@ -10,6 +22,8 @@ interface Configuration {
|
|
|
10
22
|
classPrefix?: string;
|
|
11
23
|
}
|
|
12
24
|
declare function ecij({
|
|
25
|
+
include,
|
|
26
|
+
exclude,
|
|
13
27
|
classPrefix
|
|
14
28
|
}?: Configuration): Plugin;
|
|
15
29
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -2,62 +2,75 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { relative } from "node:path";
|
|
3
3
|
import { cwd } from "node:process";
|
|
4
4
|
import { Visitor, parseSync } from "oxc-parser";
|
|
5
|
+
import { makeIdFiltersToMatchWithQuery } from "@rolldown/pluginutils";
|
|
5
6
|
|
|
6
7
|
//#region src/index.ts
|
|
7
|
-
const JS_TS_FILE_REGEX = /\.[
|
|
8
|
+
const JS_TS_FILE_REGEX = /\.[cm]?[jt]sx?$/;
|
|
9
|
+
const NODE_MODULES_REGEX = /\/node_modules\//;
|
|
10
|
+
const D_TS_FILE_REGEX = /\.d\.ts$/;
|
|
8
11
|
const PROJECT_ROOT = cwd();
|
|
9
12
|
function hashText(text) {
|
|
10
13
|
return createHash("md5").update(text).digest("hex").slice(0, 8);
|
|
11
14
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
function removeImport(code) {
|
|
16
|
-
return code.replace(/import\s+{\s*css\s*}\s+from\s+['"]ecij['"];?\s*/g, "");
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Adds import for CSS module at the top of the file
|
|
20
|
-
*/
|
|
21
|
-
function addCssImport(code, cssModuleId) {
|
|
22
|
-
return `import ${JSON.stringify(cssModuleId)};\n\n${code}`;
|
|
23
|
-
}
|
|
24
|
-
function ecij({ classPrefix = "css-" } = {}) {
|
|
15
|
+
function ecij({ include = JS_TS_FILE_REGEX, exclude = [NODE_MODULES_REGEX, D_TS_FILE_REGEX], classPrefix = "css-" } = {}) {
|
|
16
|
+
const parsedFileInfoCache = /* @__PURE__ */ new Map();
|
|
25
17
|
const extractedCssPerFile = /* @__PURE__ */ new Map();
|
|
26
|
-
const importedClassNameCache = /* @__PURE__ */ new Map();
|
|
27
|
-
/**
|
|
28
|
-
* Generates a consistent, unique class name based on file path and variable name or index
|
|
29
|
-
*/
|
|
30
|
-
function generateClassName(filePath, index, variableName) {
|
|
31
|
-
return `${classPrefix}${hashText(`${relative(PROJECT_ROOT, filePath).replaceAll("\\", "/")}:${index}:${variableName}`)}`;
|
|
32
|
-
}
|
|
33
18
|
/**
|
|
34
|
-
*
|
|
19
|
+
* Parses a file and extracts all relevant information in a single pass
|
|
35
20
|
*/
|
|
36
|
-
async function
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const
|
|
21
|
+
async function parseFile(context, filePath, code) {
|
|
22
|
+
if (code === void 0 && parsedFileInfoCache.has(filePath)) return parsedFileInfoCache.get(filePath);
|
|
23
|
+
const relativePath = relative(PROJECT_ROOT, filePath).replaceAll("\\", "/");
|
|
24
|
+
const parseResult = parseSync(filePath, code ?? await context.fs.readFile(filePath, { encoding: "utf8" }));
|
|
25
|
+
const declarations = [];
|
|
26
|
+
const localIdentifiers = /* @__PURE__ */ new Map();
|
|
27
|
+
const importedIdentifiers = /* @__PURE__ */ new Map();
|
|
28
|
+
const exportNameToValueMap = /* @__PURE__ */ new Map();
|
|
43
29
|
const localNameToExportedNameMap = /* @__PURE__ */ new Map();
|
|
30
|
+
const taggedTemplateExpressionFromVariableDeclarator = /* @__PURE__ */ new Set();
|
|
31
|
+
let hasCSSTagImport = false;
|
|
32
|
+
const parsedInfo = {
|
|
33
|
+
declarations,
|
|
34
|
+
localIdentifiers,
|
|
35
|
+
importedIdentifiers,
|
|
36
|
+
exportNameToValueMap
|
|
37
|
+
};
|
|
38
|
+
parsedFileInfoCache.set(filePath, parsedInfo);
|
|
39
|
+
for (const staticImport of parseResult.module.staticImports) for (const entry of staticImport.entries) if (entry.importName.kind === "Name") {
|
|
40
|
+
const source = staticImport.moduleRequest.value;
|
|
41
|
+
const imported = entry.importName.name;
|
|
42
|
+
const localName = entry.localName.value;
|
|
43
|
+
if (source === "ecij" && imported === "css" && localName === "css") hasCSSTagImport = true;
|
|
44
|
+
importedIdentifiers.set(localName, {
|
|
45
|
+
source,
|
|
46
|
+
imported
|
|
47
|
+
});
|
|
48
|
+
}
|
|
44
49
|
for (const staticExport of parseResult.module.staticExports) for (const entry of staticExport.entries) {
|
|
45
50
|
if (entry.importName.kind !== "None") continue;
|
|
46
51
|
if (entry.exportName.kind === "Name" && entry.localName.kind === "Name") {
|
|
47
52
|
const localName = entry.localName.name;
|
|
48
|
-
const exportedName
|
|
49
|
-
localNameToExportedNameMap.set(localName, exportedName
|
|
53
|
+
const exportedName = entry.exportName.name;
|
|
54
|
+
localNameToExportedNameMap.set(localName, exportedName);
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
function recordIdentifierWithValue(localName, value) {
|
|
58
|
+
localIdentifiers.set(localName, value);
|
|
59
|
+
if (localNameToExportedNameMap.has(localName)) {
|
|
60
|
+
const exportedName = localNameToExportedNameMap.get(localName);
|
|
61
|
+
exportNameToValueMap.set(exportedName, value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function handleTaggedTemplateExpression(localName, node) {
|
|
65
|
+
if (!(hasCSSTagImport && node.tag.type === "Identifier" && node.tag.name === "css")) return;
|
|
66
|
+
const index = declarations.length;
|
|
67
|
+
const className = `${classPrefix}${hashText(`${relativePath}:${index}:${localName}`)}`;
|
|
68
|
+
declarations.push({
|
|
69
|
+
className,
|
|
58
70
|
node,
|
|
59
|
-
hasInterpolations: node.quasi.expressions.length
|
|
71
|
+
hasInterpolations: node.quasi.expressions.length !== 0
|
|
60
72
|
});
|
|
73
|
+
if (localName !== void 0) recordIdentifierWithValue(localName, className);
|
|
61
74
|
}
|
|
62
75
|
new Visitor({
|
|
63
76
|
VariableDeclarator(node) {
|
|
@@ -66,85 +79,48 @@ function ecij({ classPrefix = "css-" } = {}) {
|
|
|
66
79
|
if (node.init.type === "TaggedTemplateExpression") {
|
|
67
80
|
taggedTemplateExpressionFromVariableDeclarator.add(node.init);
|
|
68
81
|
handleTaggedTemplateExpression(localName, node.init);
|
|
69
|
-
} else if (node.init.type === "Literal" && typeof node.init.value === "string")
|
|
70
|
-
const exportedName$1 = localNameToExportedNameMap.get(localName);
|
|
71
|
-
if (exportedName$1 === void 0) return;
|
|
72
|
-
const cacheKey$1 = `${resolvedPath}:${exportedName$1}`;
|
|
73
|
-
importedClassNameCache.set(cacheKey$1, node.init.value);
|
|
74
|
-
}
|
|
82
|
+
} else if (node.init.type === "Literal" && (typeof node.init.value === "string" || typeof node.init.value === "number")) recordIdentifierWithValue(localName, String(node.init.value));
|
|
75
83
|
},
|
|
76
84
|
TaggedTemplateExpression(node) {
|
|
77
|
-
if (taggedTemplateExpressionFromVariableDeclarator.has(node))
|
|
78
|
-
handleTaggedTemplateExpression(void 0, node);
|
|
85
|
+
if (!taggedTemplateExpressionFromVariableDeclarator.has(node)) handleTaggedTemplateExpression(void 0, node);
|
|
79
86
|
}
|
|
80
87
|
}).visit(parseResult.program);
|
|
81
|
-
|
|
82
|
-
const localName = declaration.varName;
|
|
83
|
-
if (localName === void 0) continue;
|
|
84
|
-
const exportedName$1 = localNameToExportedNameMap.get(localName);
|
|
85
|
-
if (exportedName$1 === void 0) continue;
|
|
86
|
-
const cacheKey$1 = `${resolvedPath}:${exportedName$1}`;
|
|
87
|
-
const className = generateClassName(resolvedPath, declaration.index, localName);
|
|
88
|
-
importedClassNameCache.set(cacheKey$1, className);
|
|
89
|
-
}
|
|
90
|
-
return importedClassNameCache.get(cacheKey);
|
|
88
|
+
return parsedInfo;
|
|
91
89
|
}
|
|
92
90
|
/**
|
|
93
91
|
* Extracts CSS from template literals in the source code using AST parsing
|
|
94
|
-
* Supports interpolations of
|
|
92
|
+
* Supports interpolations of strings and numbers (both local and imported)
|
|
95
93
|
*/
|
|
96
94
|
async function extractCssFromCode(context, code, filePath) {
|
|
95
|
+
const { declarations, localIdentifiers, importedIdentifiers } = await parseFile(context, filePath, code);
|
|
97
96
|
const cssExtractions = [];
|
|
98
97
|
const replacements = [];
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
98
|
+
const modulesWithSideEffects = /* @__PURE__ */ new Set();
|
|
99
|
+
async function resolveValue(identifierName) {
|
|
100
|
+
if (localIdentifiers.has(identifierName)) return localIdentifiers.get(identifierName);
|
|
101
|
+
if (importedIdentifiers.has(identifierName)) {
|
|
102
|
+
const { source, imported } = importedIdentifiers.get(identifierName);
|
|
103
|
+
const resolvedId = await context.resolve(source, filePath);
|
|
104
|
+
if (resolvedId != null) {
|
|
105
|
+
const { id } = resolvedId;
|
|
106
|
+
const { declarations: declarations$1, exportNameToValueMap } = await parseFile(context, id);
|
|
107
|
+
if (exportNameToValueMap.has(imported)) {
|
|
108
|
+
if (declarations$1.length !== 0) modulesWithSideEffects.add(id);
|
|
109
|
+
return exportNameToValueMap.get(imported);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
106
112
|
}
|
|
107
113
|
}
|
|
108
|
-
const parseResult = parseSync(filePath, code);
|
|
109
|
-
for (const staticImport of parseResult.module.staticImports) for (const entry of staticImport.entries) if (entry.importName.kind === "Name") imports.set(entry.localName.value, {
|
|
110
|
-
source: staticImport.moduleRequest.value,
|
|
111
|
-
imported: entry.importName.name
|
|
112
|
-
});
|
|
113
|
-
const declarations = [];
|
|
114
|
-
const taggedTemplateExpressionFromVariableDeclarator = /* @__PURE__ */ new Set();
|
|
115
|
-
function handleTaggedTemplateExpression(varName, node) {
|
|
116
|
-
if (node.tag.type === "Identifier" && node.tag.name === "css") declarations.push({
|
|
117
|
-
index: declarations.length,
|
|
118
|
-
varName,
|
|
119
|
-
node,
|
|
120
|
-
hasInterpolations: node.quasi.expressions.length > 0
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
new Visitor({
|
|
124
|
-
VariableDeclarator(node) {
|
|
125
|
-
if (node.init === null || node.id.type !== "Identifier") return;
|
|
126
|
-
const localName = node.id.name;
|
|
127
|
-
if (node.init.type === "TaggedTemplateExpression") {
|
|
128
|
-
taggedTemplateExpressionFromVariableDeclarator.add(node.init);
|
|
129
|
-
handleTaggedTemplateExpression(localName, node.init);
|
|
130
|
-
} else if (node.init.type === "Literal" && typeof node.init.value === "string") localClassNames.set(localName, node.init.value);
|
|
131
|
-
},
|
|
132
|
-
TaggedTemplateExpression(node) {
|
|
133
|
-
if (taggedTemplateExpressionFromVariableDeclarator.has(node)) return;
|
|
134
|
-
handleTaggedTemplateExpression(void 0, node);
|
|
135
|
-
}
|
|
136
|
-
}).visit(parseResult.program);
|
|
137
114
|
function addProcessedDeclaration(declaration, cssContent$1) {
|
|
138
|
-
const className
|
|
139
|
-
if (declaration.varName) localClassNames.set(declaration.varName, className);
|
|
115
|
+
const { className, node } = declaration;
|
|
140
116
|
cssExtractions.push({
|
|
141
117
|
className,
|
|
142
118
|
cssContent: cssContent$1.trim(),
|
|
143
|
-
sourcePosition:
|
|
119
|
+
sourcePosition: node.start
|
|
144
120
|
});
|
|
145
121
|
replacements.push({
|
|
146
|
-
start:
|
|
147
|
-
end:
|
|
122
|
+
start: node.start,
|
|
123
|
+
end: node.end,
|
|
148
124
|
className
|
|
149
125
|
});
|
|
150
126
|
}
|
|
@@ -167,12 +143,12 @@ function ecij({ classPrefix = "css-" } = {}) {
|
|
|
167
143
|
break;
|
|
168
144
|
}
|
|
169
145
|
const identifierName = expression.name;
|
|
170
|
-
const
|
|
171
|
-
if (
|
|
146
|
+
const resolvedValue = await resolveValue(identifierName);
|
|
147
|
+
if (resolvedValue === void 0) {
|
|
172
148
|
allResolved = false;
|
|
173
149
|
break;
|
|
174
150
|
}
|
|
175
|
-
cssContent$1 +=
|
|
151
|
+
cssContent$1 += resolvedValue;
|
|
176
152
|
}
|
|
177
153
|
}
|
|
178
154
|
if (allResolved) addProcessedDeclaration(declaration, cssContent$1);
|
|
@@ -181,12 +157,11 @@ function ecij({ classPrefix = "css-" } = {}) {
|
|
|
181
157
|
transformedCode: code,
|
|
182
158
|
hasExtractions: false,
|
|
183
159
|
cssContent: "",
|
|
184
|
-
|
|
160
|
+
modulesWithSideEffects
|
|
185
161
|
};
|
|
186
162
|
replacements.sort((a, b) => b.start - a.start);
|
|
187
163
|
let transformedCode = code;
|
|
188
164
|
for (const { start, end, className } of replacements) transformedCode = `${transformedCode.slice(0, start)}'${className}'${transformedCode.slice(end)}`;
|
|
189
|
-
const hasUnprocessedCssBlocks = declarations.length > replacements.length;
|
|
190
165
|
cssExtractions.sort((a, b) => a.sourcePosition - b.sourcePosition);
|
|
191
166
|
const cssBlocks = [];
|
|
192
167
|
for (const { className, cssContent: cssContent$1 } of cssExtractions) if (cssContent$1 !== "") cssBlocks.push(`.${className} {\n ${cssContent$1}\n}`);
|
|
@@ -195,38 +170,43 @@ function ecij({ classPrefix = "css-" } = {}) {
|
|
|
195
170
|
transformedCode,
|
|
196
171
|
hasExtractions: true,
|
|
197
172
|
cssContent,
|
|
198
|
-
|
|
173
|
+
modulesWithSideEffects
|
|
199
174
|
};
|
|
200
175
|
}
|
|
201
176
|
return {
|
|
202
177
|
name: "ecij",
|
|
203
|
-
|
|
178
|
+
buildEnd() {
|
|
179
|
+
parsedFileInfoCache.clear();
|
|
204
180
|
extractedCssPerFile.clear();
|
|
205
|
-
importedClassNameCache.clear();
|
|
206
181
|
},
|
|
207
182
|
resolveId(id) {
|
|
208
|
-
if (extractedCssPerFile.has(id)) return
|
|
183
|
+
if (extractedCssPerFile.has(id)) return id;
|
|
184
|
+
if (parsedFileInfoCache.has(id) && parsedFileInfoCache.get(id).declarations.length !== 0) return id;
|
|
209
185
|
return null;
|
|
210
186
|
},
|
|
211
187
|
load(id) {
|
|
212
188
|
if (extractedCssPerFile.has(id)) return extractedCssPerFile.get(id);
|
|
213
189
|
return null;
|
|
214
190
|
},
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
191
|
+
transform: {
|
|
192
|
+
filter: { id: {
|
|
193
|
+
include: makeIdFiltersToMatchWithQuery(include),
|
|
194
|
+
exclude: makeIdFiltersToMatchWithQuery(exclude)
|
|
195
|
+
} },
|
|
196
|
+
async handler(code, id) {
|
|
197
|
+
if (!code.includes("ecij")) return null;
|
|
198
|
+
const queryIndex = id.indexOf("?");
|
|
199
|
+
const cleanId = queryIndex === -1 ? id : id.slice(0, queryIndex);
|
|
200
|
+
const { transformedCode, hasExtractions, cssContent, modulesWithSideEffects } = await extractCssFromCode(this, code, cleanId);
|
|
201
|
+
if (!hasExtractions) return null;
|
|
202
|
+
if (cssContent === "") return transformedCode;
|
|
224
203
|
const cssModuleId = `${cleanId}.${hashText(cssContent)}.css`;
|
|
225
204
|
extractedCssPerFile.set(cssModuleId, cssContent);
|
|
226
|
-
|
|
205
|
+
const importStatements = [];
|
|
206
|
+
for (const id$1 of modulesWithSideEffects) importStatements.push(`import ${JSON.stringify(id$1)};\n`);
|
|
207
|
+
importStatements.push(`import ${JSON.stringify(cssModuleId)}\n;`);
|
|
208
|
+
return `${importStatements.join("")}${transformedCode}`;
|
|
227
209
|
}
|
|
228
|
-
if (!hasUnprocessedCssBlocks) finalCode = removeImport(finalCode);
|
|
229
|
-
return finalCode;
|
|
230
210
|
}
|
|
231
211
|
};
|
|
232
212
|
}
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ecij",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Rolldown and Vite plugin to Extract CSS-in-JS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css-in-js"
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"author": "Nicolas Stepien",
|
|
18
18
|
"type": "module",
|
|
19
|
+
"sideEffects": false,
|
|
19
20
|
"exports": {
|
|
20
21
|
".": {
|
|
21
22
|
"types": "./index.d.ts",
|
|
@@ -35,16 +36,25 @@
|
|
|
35
36
|
"build": "rolldown -c",
|
|
36
37
|
"format": "prettier --write .",
|
|
37
38
|
"format:check": "prettier --check .",
|
|
38
|
-
"typecheck": "tsc"
|
|
39
|
+
"typecheck": "tsc --build",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:coverage": "vitest run --coverage"
|
|
39
42
|
},
|
|
40
43
|
"dependencies": {
|
|
41
|
-
"
|
|
44
|
+
"@rolldown/pluginutils": "^1.0.0-beta.53",
|
|
45
|
+
"oxc-parser": "^0.102.0"
|
|
42
46
|
},
|
|
43
47
|
"devDependencies": {
|
|
44
48
|
"@types/node": "^24.10.1",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"rolldown
|
|
48
|
-
"
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
50
|
+
"prettier": "^3.7.4",
|
|
51
|
+
"rolldown": "^1.0.0-beta.53",
|
|
52
|
+
"rolldown-plugin-dts": "^0.18.3",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vite": "npm:rolldown-vite@^7.2.10",
|
|
55
|
+
"vitest": "^4.0.15"
|
|
56
|
+
},
|
|
57
|
+
"overrides": {
|
|
58
|
+
"vite": "$vite"
|
|
49
59
|
}
|
|
50
60
|
}
|