@stylexswc/postcss-plugin 0.15.1-rc.2 → 0.15.2-rc.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.
- package/README.md +54 -13
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +94 -19
- package/dist/bundler.d.ts +2 -2
- package/dist/bundler.d.ts.map +1 -1
- package/dist/bundler.js +4 -8
- package/dist/discovery.d.ts +49 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +277 -0
- package/dist/index.d.ts +1 -1
- package/dist/plugin.d.ts +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +39 -6
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types.d.ts +11 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# PostCSS plugin with NAPI-RS StyleX compiler integration
|
|
2
2
|
|
|
3
|
+
> Part of the
|
|
4
|
+
> [StyleX SWC Plugin](https://github.com/Dwlad90/stylex-swc-plugin#readme)
|
|
5
|
+
> workspace
|
|
6
|
+
|
|
3
7
|
`PostCSS plugin` for an unofficial
|
|
4
8
|
[`napi-rs`](https://github.com/dwlad90/stylex-swc-plugin/tree/develop/crates/stylex-rs-compiler)
|
|
5
9
|
compiler that includes the StyleX SWC code transformation under the hood.
|
|
@@ -103,33 +107,46 @@ import '[fileName].css';
|
|
|
103
107
|
The plugin accepts the following configuration options:
|
|
104
108
|
|
|
105
109
|
> [!NOTE]
|
|
106
|
-
> **Features:** The `include` and `exclude` options are exclusive to
|
|
110
|
+
> **Features:** The `include` and `exclude` options are exclusive to
|
|
111
|
+
> this NAPI-RS compiler implementation and are not available in the official
|
|
112
|
+
> StyleX Babel plugin.
|
|
107
113
|
|
|
108
114
|
### `include`
|
|
109
115
|
|
|
110
116
|
- Type: `(string | RegExp)[]`
|
|
111
|
-
-
|
|
112
|
-
- Description: **RS-compiler Only** An array of glob patterns or regular
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
- Default: auto-discovered
|
|
118
|
+
- Description: **RS-compiler Only** An array of glob patterns or regular
|
|
119
|
+
expressions to include specific files for StyleX transformation. When
|
|
120
|
+
specified, only files matching at least one of these patterns will be
|
|
121
|
+
discovered and transformed. Patterns are matched against paths relative to the
|
|
122
|
+
current working directory. Supports regex lookahead/lookbehind for advanced
|
|
123
|
+
filtering.
|
|
124
|
+
|
|
125
|
+
When omitted, the plugin auto-discovers source files in the project `cwd` and
|
|
126
|
+
direct dependencies that use StyleX.
|
|
116
127
|
|
|
117
128
|
### `exclude`
|
|
118
129
|
|
|
119
130
|
- Type: `(string | RegExp)[]`
|
|
120
131
|
- Optional
|
|
121
|
-
- Description: **RS-compiler Only** An array of glob patterns or regular
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
132
|
+
- Description: **RS-compiler Only** An array of glob patterns or regular
|
|
133
|
+
expressions to exclude specific files from StyleX transformation. Files
|
|
134
|
+
matching any of these patterns will not be transformed, even if they match an
|
|
135
|
+
`include` pattern. Patterns are matched against paths relative to the current
|
|
136
|
+
working directory. Supports regex lookahead/lookbehind for advanced filtering.
|
|
137
|
+
|
|
138
|
+
When `include` is omitted, the plugin automatically excludes common build and
|
|
139
|
+
dependency folders (for example `node_modules`, `.next`, `dist`, `build`) to
|
|
140
|
+
keep discovery focused on source files.
|
|
125
141
|
|
|
126
142
|
### `rsOptions`
|
|
127
143
|
|
|
128
144
|
- Type: `StyleXOptions`
|
|
129
145
|
- Optional
|
|
130
146
|
- Default: `{}`
|
|
131
|
-
- Description: StyleX compiler options passed to the StyleX compiler.
|
|
132
|
-
|
|
147
|
+
- Description: StyleX compiler options passed to the StyleX compiler. For
|
|
148
|
+
standard StyleX options, see the
|
|
149
|
+
[official StyleX documentation](https://stylexjs.com/docs/api/configuration/babel-plugin/).
|
|
133
150
|
|
|
134
151
|
### `useCSSLayers`
|
|
135
152
|
|
|
@@ -143,7 +160,8 @@ The plugin accepts the following configuration options:
|
|
|
143
160
|
- Type: `string`
|
|
144
161
|
- Optional
|
|
145
162
|
- Default: `process.cwd()`
|
|
146
|
-
- Description: Current working directory for resolving files
|
|
163
|
+
- Description: Current working directory for resolving files. Dependency paths
|
|
164
|
+
and config resolution use this value.
|
|
147
165
|
|
|
148
166
|
### `isDev`
|
|
149
167
|
|
|
@@ -151,6 +169,16 @@ The plugin accepts the following configuration options:
|
|
|
151
169
|
- Optional
|
|
152
170
|
- Description: Whether the plugin is running in development mode
|
|
153
171
|
|
|
172
|
+
### `importSources`
|
|
173
|
+
|
|
174
|
+
- Type: `Array<string | { from: string, as: string }>`
|
|
175
|
+
- Optional
|
|
176
|
+
- Description: Override import sources at the PostCSS plugin level.
|
|
177
|
+
|
|
178
|
+
When provided, takes precedence over `rsOptions.importSources`. When omitted,
|
|
179
|
+
falls back to `rsOptions.importSources`, then the built-in defaults
|
|
180
|
+
(`@stylexjs/stylex`, `stylex`).
|
|
181
|
+
|
|
154
182
|
## Path Filtering Examples
|
|
155
183
|
|
|
156
184
|
**Include only specific directories:**
|
|
@@ -211,3 +239,16 @@ The plugin accepts the following configuration options:
|
|
|
211
239
|
},
|
|
212
240
|
}
|
|
213
241
|
```
|
|
242
|
+
|
|
243
|
+
## Debugging auto-discovery
|
|
244
|
+
|
|
245
|
+
Set `STYLEX_POSTCSS_DEBUG=1` to print resolved plugin inputs, including:
|
|
246
|
+
|
|
247
|
+
- resolved `importSources` and where they came from
|
|
248
|
+
- final `include` and `exclude` globs
|
|
249
|
+
- discovered dependency directories
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT — see
|
|
254
|
+
[LICENSE](https://github.com/Dwlad90/stylex-swc-plugin/blob/develop/LICENSE)
|
package/dist/builder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAU1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/builder.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAU1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA2GpE,iBAAS,aAAa;6BAsBY,OAAO,CAAC,IAAI,KAAG,MAAM,GAAG,IAAI;yBAdhC,kBAAkB;0CA8FD,gBAAgB;;cAtKjD,gBAAgB;aAAO,MAAM;cAAQ,MAAM;;cAC3C,YAAY;cAAQ,MAAM;;EA0PvC;AAED,eAAe,aAAa,CAAC"}
|
package/dist/builder.js
CHANGED
|
@@ -11,6 +11,10 @@ const is_glob_1 = __importDefault(require("is-glob"));
|
|
|
11
11
|
const glob_parent_1 = __importDefault(require("glob-parent"));
|
|
12
12
|
const bundler_1 = __importDefault(require("./bundler"));
|
|
13
13
|
const rs_compiler_1 = require("@stylexswc/rs-compiler");
|
|
14
|
+
const NODE_MODULES_CATCH_ALL_EXCLUDE_PATTERNS = new Set([
|
|
15
|
+
'node_modules/**',
|
|
16
|
+
'**/node_modules/**',
|
|
17
|
+
]);
|
|
14
18
|
// Parses a glob pattern and extracts its base directory and pattern.
|
|
15
19
|
// Returns an object with `base` and `glob` properties.
|
|
16
20
|
function parseGlob(pattern) {
|
|
@@ -34,7 +38,7 @@ function parseGlob(pattern) {
|
|
|
34
38
|
return { base, glob };
|
|
35
39
|
}
|
|
36
40
|
// Parses a file path or glob pattern into a PostCSS dependency message.
|
|
37
|
-
function parseDependency(fileOrGlob) {
|
|
41
|
+
function parseDependency(fileOrGlob, cwd) {
|
|
38
42
|
// License: MIT
|
|
39
43
|
// Based on:
|
|
40
44
|
// https://github.com/chakra-ui/panda/blob/6ab003795c0b076efe6879a2e6a2a548cb96580e/packages/node/src/parse-dependency.ts
|
|
@@ -44,13 +48,57 @@ function parseDependency(fileOrGlob) {
|
|
|
44
48
|
let message;
|
|
45
49
|
if ((0, is_glob_1.default)(fileOrGlob)) {
|
|
46
50
|
const { base, glob } = parseGlob(fileOrGlob);
|
|
47
|
-
message = {
|
|
51
|
+
message = {
|
|
52
|
+
type: 'dir-dependency',
|
|
53
|
+
dir: (0, path_1.normalize)((0, path_1.resolve)(cwd, base)),
|
|
54
|
+
glob,
|
|
55
|
+
};
|
|
48
56
|
}
|
|
49
57
|
else {
|
|
50
|
-
message = { type: 'dependency', file: (0, path_1.normalize)((0, path_1.resolve)(fileOrGlob)) };
|
|
58
|
+
message = { type: 'dependency', file: (0, path_1.normalize)((0, path_1.resolve)(cwd, fileOrGlob)) };
|
|
51
59
|
}
|
|
52
60
|
return message;
|
|
53
61
|
}
|
|
62
|
+
function normalizeGlobPattern(pattern) {
|
|
63
|
+
return String(pattern).replace(/\\/g, '/').replace(/^\.\//, '');
|
|
64
|
+
}
|
|
65
|
+
function isNodeModulesCatchAllExcludePattern(pattern) {
|
|
66
|
+
return NODE_MODULES_CATCH_ALL_EXCLUDE_PATTERNS.has(normalizeGlobPattern(pattern));
|
|
67
|
+
}
|
|
68
|
+
function toCanonicalFilePath(file, cwd) {
|
|
69
|
+
return (0, path_1.normalize)((0, path_1.resolve)(cwd, file));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* When an absolute include pattern points into node_modules, we remove the broad
|
|
73
|
+
* catch-all excludes (node_modules/** and **\/node_modules/**) so the specific
|
|
74
|
+
* package path can be matched. However that also allows deeply nested
|
|
75
|
+
* node_modules within the discovered package (e.g. transitive deps that
|
|
76
|
+
* themselves have their own node_modules) to be scanned.
|
|
77
|
+
*
|
|
78
|
+
* This helper computes a *specific* absolute exclude pattern that prevents
|
|
79
|
+
* scanning the nested node_modules inside the matched package's base directory,
|
|
80
|
+
* while still letting the package's own source files through.
|
|
81
|
+
*
|
|
82
|
+
* The pattern must be absolute because fast-glob does not apply relative ignore
|
|
83
|
+
* patterns to absolute match results (which occur when the include pattern is
|
|
84
|
+
* itself absolute).
|
|
85
|
+
*
|
|
86
|
+
* Example:
|
|
87
|
+
* includePattern = '/app/node_modules/@acme/ui/**\/*.{ts,tsx}'
|
|
88
|
+
* → '/app/node_modules/@acme/ui/node_modules/**'
|
|
89
|
+
*/
|
|
90
|
+
function nestedNodeModulesExcludeFor(includePattern) {
|
|
91
|
+
if (!node_path_1.default.isAbsolute(includePattern)) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
// globParent gives the base directory before the glob wildcards begin.
|
|
95
|
+
// e.g. '/app/node_modules/@acme/ui/**/*.ts' → '/app/node_modules/@acme/ui'
|
|
96
|
+
const baseDir = (0, glob_parent_1.default)(includePattern);
|
|
97
|
+
// Return an absolute ignore pattern so fast-glob matches it correctly
|
|
98
|
+
// when the include pattern is absolute (relative ignore patterns are not
|
|
99
|
+
// applied to absolute match results).
|
|
100
|
+
return `${baseDir.split(node_path_1.default.sep).join('/')}/node_modules/**`;
|
|
101
|
+
}
|
|
54
102
|
// Creates a builder for transforming files and bundling StyleX CSS.
|
|
55
103
|
function createBuilder() {
|
|
56
104
|
let config = null;
|
|
@@ -86,24 +134,55 @@ function createBuilder() {
|
|
|
86
134
|
const isGlobPattern = (p) => !isRegexPattern(p);
|
|
87
135
|
const globPatterns = (include || []).filter(isGlobPattern).map(p => String(p));
|
|
88
136
|
const hasRegexPatterns = (include || []).some(isRegexPattern) || (exclude || []).some(isRegexPattern);
|
|
137
|
+
if (globPatterns.length === 0 && !hasRegexPatterns) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
89
140
|
// Use fast-glob with glob patterns for initial discovery
|
|
90
141
|
const globExclude = (exclude || []).filter(isGlobPattern).map(p => String(p));
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
142
|
+
const ignoreWithoutNodeModulesCatchAll = globExclude.filter((pattern) => !isNodeModulesCatchAllExcludePattern(pattern));
|
|
143
|
+
const files = new Set();
|
|
144
|
+
for (const includePattern of globPatterns) {
|
|
145
|
+
const isAbsolutePattern = node_path_1.default.isAbsolute(includePattern);
|
|
146
|
+
const pointsToNodeModules = /(^|[/\\])node_modules([/\\]|$)/.test(includePattern);
|
|
147
|
+
let ignore;
|
|
148
|
+
if (isAbsolutePattern && pointsToNodeModules) {
|
|
149
|
+
// Remove broad catch-all patterns so this specific node_modules path
|
|
150
|
+
// can be matched, but add back a targeted exclude for any nested
|
|
151
|
+
// node_modules *within* the matched package to avoid scanning
|
|
152
|
+
// transitive dependencies' source files.
|
|
153
|
+
const nestedExclude = nestedNodeModulesExcludeFor(includePattern);
|
|
154
|
+
ignore = [
|
|
155
|
+
...ignoreWithoutNodeModulesCatchAll,
|
|
156
|
+
...(nestedExclude != null ? [nestedExclude] : []),
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
ignore = globExclude;
|
|
161
|
+
}
|
|
162
|
+
const matchedFiles = (0, fast_glob_1.globSync)(includePattern, {
|
|
163
|
+
onlyFiles: true,
|
|
164
|
+
ignore,
|
|
165
|
+
cwd,
|
|
166
|
+
});
|
|
167
|
+
for (const file of matchedFiles) {
|
|
168
|
+
files.add(toCanonicalFilePath(file, cwd || '/'));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
let result = Array.from(files);
|
|
98
172
|
// If there are regex patterns, filter using shouldTransformFile
|
|
99
173
|
if (hasRegexPatterns) {
|
|
100
|
-
|
|
174
|
+
result = result.filter(file => (0, rs_compiler_1.shouldTransformFile)(file, include, exclude));
|
|
101
175
|
}
|
|
102
|
-
return
|
|
176
|
+
return result;
|
|
103
177
|
}
|
|
104
178
|
// Transforms the included files, bundles the CSS, and returns the result.
|
|
105
179
|
function build({ shouldSkipTransformError }) {
|
|
106
180
|
const { cwd, rsOptions, useCSSLayers, isDev } = getConfig();
|
|
181
|
+
const transformedOptions = {
|
|
182
|
+
useLayers: useCSSLayers,
|
|
183
|
+
enableLTRRTLComments: rsOptions?.enableLTRRTLComments,
|
|
184
|
+
legacyDisableLayers: rsOptions?.legacyDisableLayers,
|
|
185
|
+
};
|
|
107
186
|
const files = getFiles();
|
|
108
187
|
const filesToTransform = [];
|
|
109
188
|
// Remove deleted files since the last build
|
|
@@ -143,20 +222,16 @@ function createBuilder() {
|
|
|
143
222
|
});
|
|
144
223
|
return transformedResult;
|
|
145
224
|
});
|
|
146
|
-
const css = bundler.bundle(
|
|
147
|
-
useCSSLayers,
|
|
148
|
-
enableLTRRTLComments: rsOptions?.enableLTRRTLComments,
|
|
149
|
-
legacyDisableLayers: rsOptions?.legacyDisableLayers,
|
|
150
|
-
});
|
|
225
|
+
const css = bundler.bundle(transformedOptions);
|
|
151
226
|
return css;
|
|
152
227
|
}
|
|
153
228
|
// Retrieves the dependencies that PostCSS should watch.
|
|
154
229
|
function getDependencies() {
|
|
155
|
-
const { include } = getConfig();
|
|
230
|
+
const { include, cwd } = getConfig();
|
|
156
231
|
const dependencies = [];
|
|
157
232
|
for (const fileOrGlob of include || []) {
|
|
158
233
|
const fileOrGlobString = fileOrGlob.toString();
|
|
159
|
-
const dependency = parseDependency(fileOrGlobString);
|
|
234
|
+
const dependency = parseDependency(fileOrGlobString, cwd || process.cwd());
|
|
160
235
|
if (dependency != null) {
|
|
161
236
|
dependencies.push(dependency);
|
|
162
237
|
}
|
package/dist/bundler.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { StyleXOptions } from '@stylexswc/rs-compiler';
|
|
1
|
+
import type { StyleXOptions, TransformedOptions } from '@stylexswc/rs-compiler';
|
|
2
2
|
import type { TransformOptions, StyleXPluginOption } from './types';
|
|
3
3
|
export default function createBundler(): {
|
|
4
4
|
shouldTransform: (sourceCode: string, rsOptions?: StyleXPluginOption["rsOptions"]) => boolean | undefined;
|
|
5
5
|
transform: (id: string, sourceCode: string, rsOptions: StyleXOptions, options: TransformOptions) => import("@stylexswc/rs-compiler").StyleXTransformResult;
|
|
6
6
|
remove: (id: string) => void;
|
|
7
|
-
bundle: (
|
|
7
|
+
bundle: (transformedOptions: TransformedOptions) => string;
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=bundler.d.ts.map
|
package/dist/bundler.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../../src/bundler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../../src/bundler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAEhF,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGpE,MAAM,CAAC,OAAO,UAAU,aAAa;kCAIE,MAAM,cAAc,kBAAkB,CAAC,WAAW,CAAC;oBAoClF,MAAM,cACE,MAAM,aACP,aAAa,WACf,gBAAgB;iBAqCP,MAAM;iCAKU,kBAAkB;EAavD"}
|
package/dist/bundler.js
CHANGED
|
@@ -15,11 +15,11 @@ function createBundler() {
|
|
|
15
15
|
let parsedImportSources;
|
|
16
16
|
try {
|
|
17
17
|
parsedImportSources = importSources?.map(importSource => {
|
|
18
|
-
|
|
19
|
-
return a;
|
|
18
|
+
return typeof importSource === 'string' ? JSON.parse(importSource) : importSource;
|
|
20
19
|
});
|
|
21
20
|
}
|
|
22
21
|
catch (error) {
|
|
22
|
+
console.warn(error);
|
|
23
23
|
parsedImportSources = importSources;
|
|
24
24
|
}
|
|
25
25
|
const shouldTransform = parsedImportSources?.some(importSource => {
|
|
@@ -69,13 +69,9 @@ function createBundler() {
|
|
|
69
69
|
styleXRulesMap.delete(id);
|
|
70
70
|
}
|
|
71
71
|
// Bundles all collected StyleX rules into a single CSS string.
|
|
72
|
-
function bundle(
|
|
72
|
+
function bundle(transformedOptions) {
|
|
73
73
|
const rules = Array.from(styleXRulesMap.values()).flat();
|
|
74
|
-
const css = babel_plugin_1.default.processStylexRules(rules,
|
|
75
|
-
useLayers: useCSSLayers,
|
|
76
|
-
enableLTRRTLComments,
|
|
77
|
-
legacyDisableLayers,
|
|
78
|
-
});
|
|
74
|
+
const css = babel_plugin_1.default.processStylexRules(rules, transformedOptions);
|
|
79
75
|
return css;
|
|
80
76
|
}
|
|
81
77
|
return {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { StyleXPluginOption } from './types';
|
|
2
|
+
type ImportSource = string | {
|
|
3
|
+
from: string;
|
|
4
|
+
as?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const DEFAULT_IMPORT_SOURCES: string[];
|
|
7
|
+
export declare const DEFAULT_INCLUDE_GLOB = "**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}";
|
|
8
|
+
export declare const AUTO_DISCOVERY_EXCLUDES: string[];
|
|
9
|
+
export interface ImportSourcesResolution {
|
|
10
|
+
importSources: ImportSource[];
|
|
11
|
+
source: 'postcss-option' | 'rs-options' | 'defaults';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the effective importSources with metadata about where they came from.
|
|
15
|
+
*
|
|
16
|
+
* Precedence:
|
|
17
|
+
* 1. Explicit PostCSS `importSources` option
|
|
18
|
+
* 2. Inferred from `rsOptions.importSources`
|
|
19
|
+
* 3. Built-in defaults (`@stylexjs/stylex`, `stylex`)
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveImportSourcesWithMetadata({ importSources, rsOptions, }: {
|
|
22
|
+
importSources?: ImportSource[];
|
|
23
|
+
rsOptions?: StyleXPluginOption['rsOptions'];
|
|
24
|
+
}): ImportSourcesResolution;
|
|
25
|
+
export declare function resolveImportSources({ importSources, rsOptions, }: {
|
|
26
|
+
importSources?: ImportSource[];
|
|
27
|
+
rsOptions?: StyleXPluginOption['rsOptions'];
|
|
28
|
+
}): ImportSource[];
|
|
29
|
+
export interface IncludeResolution {
|
|
30
|
+
include: Array<string | RegExp>;
|
|
31
|
+
discoveredDependencyDirectories: string[];
|
|
32
|
+
hasExplicitInclude: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function resolveIncludeWithMetadata({ cwd, include, importSources, }: {
|
|
35
|
+
cwd: string;
|
|
36
|
+
include?: StyleXPluginOption['include'];
|
|
37
|
+
importSources: ImportSource[];
|
|
38
|
+
}): IncludeResolution;
|
|
39
|
+
export declare function resolveInclude({ cwd, include, importSources, }: {
|
|
40
|
+
cwd: string;
|
|
41
|
+
include?: StyleXPluginOption['include'];
|
|
42
|
+
importSources: ImportSource[];
|
|
43
|
+
}): Array<string | RegExp>;
|
|
44
|
+
export declare function resolveExclude({ include, exclude, }: {
|
|
45
|
+
include?: StyleXPluginOption['include'];
|
|
46
|
+
exclude?: StyleXPluginOption['exclude'];
|
|
47
|
+
}): Array<string | RegExp>;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElD,KAAK,YAAY,GAAG,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAAmC,CAAC;AAe/E,eAAO,MAAM,oBAAoB,yCAAyC,CAAC;AAI3E,eAAO,MAAM,uBAAuB,UAcnC,CAAC;AA2OF,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,MAAM,EAAE,gBAAgB,GAAG,YAAY,GAAG,UAAU,CAAC;CACtD;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAAC,EAC/C,aAAa,EACb,SAAS,GACV,EAAE;IACD,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;CAC7C,GAAG,uBAAuB,CAuB1B;AAED,wBAAgB,oBAAoB,CAAC,EACnC,aAAa,EACb,SAAS,GACV,EAAE;IACD,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;CAC7C,GAAG,YAAY,EAAE,CAEjB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAChC,+BAA+B,EAAE,MAAM,EAAE,CAAC;IAC1C,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,0BAA0B,CAAC,EACzC,GAAG,EACH,OAAO,EACP,aAAa,GACd,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACxC,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B,GAAG,iBAAiB,CA4BpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,OAAO,EACP,aAAa,GACd,EAAE;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACxC,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAEzB;AAED,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,OAAO,GACR,EAAE;IACD,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,kBAAkB,CAAC,SAAS,CAAC,CAAC;CACzC,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CASzB"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.AUTO_DISCOVERY_EXCLUDES = exports.DEFAULT_INCLUDE_GLOB = exports.DEFAULT_IMPORT_SOURCES = void 0;
|
|
7
|
+
exports.resolveImportSourcesWithMetadata = resolveImportSourcesWithMetadata;
|
|
8
|
+
exports.resolveImportSources = resolveImportSources;
|
|
9
|
+
exports.resolveIncludeWithMetadata = resolveIncludeWithMetadata;
|
|
10
|
+
exports.resolveInclude = resolveInclude;
|
|
11
|
+
exports.resolveExclude = resolveExclude;
|
|
12
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
13
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
|
+
const node_module_1 = require("node:module");
|
|
15
|
+
exports.DEFAULT_IMPORT_SOURCES = ['@stylexjs/stylex', 'stylex'];
|
|
16
|
+
const DEFAULT_IMPORT_SOURCE_PACKAGES = new Set(exports.DEFAULT_IMPORT_SOURCES.map((source) => {
|
|
17
|
+
if (source.startsWith('@')) {
|
|
18
|
+
const parts = source.split('/');
|
|
19
|
+
const scope = parts[0];
|
|
20
|
+
const name = parts[1];
|
|
21
|
+
return scope != null && name != null ? `${scope}/${name}` : null;
|
|
22
|
+
}
|
|
23
|
+
const packageName = source.split('/')[0];
|
|
24
|
+
return packageName ?? null;
|
|
25
|
+
}).filter(Boolean));
|
|
26
|
+
exports.DEFAULT_INCLUDE_GLOB = '**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}';
|
|
27
|
+
// Keep auto-discovery focused on source files.
|
|
28
|
+
// Explicit include values from users are always respected.
|
|
29
|
+
exports.AUTO_DISCOVERY_EXCLUDES = [
|
|
30
|
+
'node_modules/**',
|
|
31
|
+
'**/node_modules/**',
|
|
32
|
+
'.git/**',
|
|
33
|
+
'.next/**',
|
|
34
|
+
'.nuxt/**',
|
|
35
|
+
'.svelte-kit/**',
|
|
36
|
+
'.turbo/**',
|
|
37
|
+
'.cache/**',
|
|
38
|
+
'dist/**',
|
|
39
|
+
'build/**',
|
|
40
|
+
'coverage/**',
|
|
41
|
+
'tmp/**',
|
|
42
|
+
'temp/**',
|
|
43
|
+
];
|
|
44
|
+
function toArray(value) {
|
|
45
|
+
if (value == null) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
return Array.isArray(value) ? value : [value];
|
|
49
|
+
}
|
|
50
|
+
function dedupe(items) {
|
|
51
|
+
return Array.from(new Set(items));
|
|
52
|
+
}
|
|
53
|
+
function readJSON(file) {
|
|
54
|
+
try {
|
|
55
|
+
const content = node_fs_1.default.readFileSync(file, 'utf8');
|
|
56
|
+
return JSON.parse(content);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function toPackageName(importSource) {
|
|
63
|
+
const source = typeof importSource === 'string'
|
|
64
|
+
? importSource
|
|
65
|
+
: importSource?.from;
|
|
66
|
+
if (source == null || source.startsWith('.') || source.startsWith('/')) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
if (source.startsWith('@')) {
|
|
70
|
+
const parts = source.split('/');
|
|
71
|
+
const scope = parts[0];
|
|
72
|
+
const name = parts[1];
|
|
73
|
+
if (scope != null && name != null) {
|
|
74
|
+
return `${scope}/${name}`;
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
const packageName = source.split('/')[0];
|
|
79
|
+
return packageName ?? null;
|
|
80
|
+
}
|
|
81
|
+
function hasStylexDependency(manifest, targetPackages) {
|
|
82
|
+
if (manifest == null || typeof manifest !== 'object') {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const dependencyFields = ['dependencies', 'peerDependencies', 'optionalDependencies'];
|
|
86
|
+
return dependencyFields.some((field) => {
|
|
87
|
+
const deps = manifest[field];
|
|
88
|
+
if (deps == null || typeof deps !== 'object') {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return Object.keys(deps).some((depName) => targetPackages.has(depName));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function findDependencyManifestPathFromEntry(entryPath, dependencyName) {
|
|
95
|
+
let dir = node_path_1.default.dirname(entryPath);
|
|
96
|
+
for (;;) {
|
|
97
|
+
const candidate = node_path_1.default.join(dir, 'package.json');
|
|
98
|
+
const manifest = readJSON(candidate);
|
|
99
|
+
if (manifest != null && manifest.name === dependencyName) {
|
|
100
|
+
return candidate;
|
|
101
|
+
}
|
|
102
|
+
const parent = node_path_1.default.dirname(dir);
|
|
103
|
+
if (parent === dir) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
dir = parent;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function resolveDependencyManifestPath(requireFromRoot, dependencyName) {
|
|
110
|
+
try {
|
|
111
|
+
return requireFromRoot.resolve(`${dependencyName}/package.json`);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// fall through
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const entryPath = requireFromRoot.resolve(dependencyName);
|
|
118
|
+
return findDependencyManifestPathFromEntry(entryPath, dependencyName);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// fall through
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function includePackageFromImportSource({ importSource, cwd, requireFromRoot, discoveredDirectories, }) {
|
|
126
|
+
const source = typeof importSource === 'string'
|
|
127
|
+
? importSource
|
|
128
|
+
: importSource?.from;
|
|
129
|
+
if (typeof source !== 'string') {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (source.startsWith('.') || source.startsWith('/')) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const packageName = toPackageName(source);
|
|
136
|
+
if (packageName == null) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (DEFAULT_IMPORT_SOURCE_PACKAGES.has(packageName)) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const manifestPath = resolveDependencyManifestPath(requireFromRoot, packageName);
|
|
143
|
+
if (manifestPath == null) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const directory = node_path_1.default.dirname(manifestPath);
|
|
147
|
+
if (directory !== node_path_1.default.resolve(cwd)) {
|
|
148
|
+
discoveredDirectories.add(directory);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function getDirectDependencies(manifest) {
|
|
152
|
+
if (manifest == null || typeof manifest !== 'object') {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
const dependencyFields = [
|
|
156
|
+
'dependencies',
|
|
157
|
+
'devDependencies',
|
|
158
|
+
'peerDependencies',
|
|
159
|
+
'optionalDependencies',
|
|
160
|
+
];
|
|
161
|
+
const dependencies = new Set();
|
|
162
|
+
for (const field of dependencyFields) {
|
|
163
|
+
const deps = manifest[field];
|
|
164
|
+
if (deps == null || typeof deps !== 'object') {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
for (const name of Object.keys(deps)) {
|
|
168
|
+
dependencies.add(name);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return Array.from(dependencies);
|
|
172
|
+
}
|
|
173
|
+
function toAbsoluteGlob(directory, globPattern) {
|
|
174
|
+
const normalizedDir = node_path_1.default.resolve(directory).split(node_path_1.default.sep).join('/');
|
|
175
|
+
return `${normalizedDir}/${globPattern}`;
|
|
176
|
+
}
|
|
177
|
+
function discoverStylexPackageDirectories({ cwd, importSources, }) {
|
|
178
|
+
const rootPackageJsonPath = node_path_1.default.join(node_path_1.default.resolve(cwd), 'package.json');
|
|
179
|
+
if (!node_fs_1.default.existsSync(rootPackageJsonPath)) {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
const rootPackageDir = node_path_1.default.dirname(rootPackageJsonPath);
|
|
183
|
+
const requireFromRoot = (0, node_module_1.createRequire)(rootPackageJsonPath);
|
|
184
|
+
const rootManifest = readJSON(rootPackageJsonPath);
|
|
185
|
+
const dependencyNames = getDirectDependencies(rootManifest);
|
|
186
|
+
const targetPackages = new Set(importSources.map(toPackageName).filter(Boolean).concat(exports.DEFAULT_IMPORT_SOURCES));
|
|
187
|
+
const discoveredDirectories = new Set();
|
|
188
|
+
for (const dependencyName of dependencyNames) {
|
|
189
|
+
const manifestPath = resolveDependencyManifestPath(requireFromRoot, dependencyName);
|
|
190
|
+
if (manifestPath == null) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const manifest = readJSON(manifestPath);
|
|
194
|
+
if (!hasStylexDependency(manifest, targetPackages)) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const dependencyDir = node_path_1.default.dirname(manifestPath);
|
|
198
|
+
// Avoid accidentally re-scanning the project root in monorepo edge cases.
|
|
199
|
+
if (dependencyDir !== rootPackageDir) {
|
|
200
|
+
discoveredDirectories.add(dependencyDir);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const importSource of importSources) {
|
|
204
|
+
includePackageFromImportSource({
|
|
205
|
+
importSource,
|
|
206
|
+
cwd,
|
|
207
|
+
requireFromRoot,
|
|
208
|
+
discoveredDirectories,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return Array.from(discoveredDirectories);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Resolves the effective importSources with metadata about where they came from.
|
|
215
|
+
*
|
|
216
|
+
* Precedence:
|
|
217
|
+
* 1. Explicit PostCSS `importSources` option
|
|
218
|
+
* 2. Inferred from `rsOptions.importSources`
|
|
219
|
+
* 3. Built-in defaults (`@stylexjs/stylex`, `stylex`)
|
|
220
|
+
*/
|
|
221
|
+
function resolveImportSourcesWithMetadata({ importSources, rsOptions, }) {
|
|
222
|
+
// 1. Explicit importSources from PostCSS plugin options
|
|
223
|
+
if (Array.isArray(importSources) && importSources.length > 0) {
|
|
224
|
+
return {
|
|
225
|
+
importSources: dedupe(importSources),
|
|
226
|
+
source: 'postcss-option',
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
// 2. Inferred from rsOptions.importSources
|
|
230
|
+
const rsImportSources = rsOptions?.importSources;
|
|
231
|
+
if (Array.isArray(rsImportSources) && rsImportSources.length > 0) {
|
|
232
|
+
return {
|
|
233
|
+
importSources: dedupe([...exports.DEFAULT_IMPORT_SOURCES, ...rsImportSources]),
|
|
234
|
+
source: 'rs-options',
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// 3. Built-in defaults
|
|
238
|
+
return {
|
|
239
|
+
importSources: exports.DEFAULT_IMPORT_SOURCES,
|
|
240
|
+
source: 'defaults',
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function resolveImportSources({ importSources, rsOptions, }) {
|
|
244
|
+
return resolveImportSourcesWithMetadata({ importSources, rsOptions }).importSources;
|
|
245
|
+
}
|
|
246
|
+
function resolveIncludeWithMetadata({ cwd, include, importSources, }) {
|
|
247
|
+
const normalizedInclude = toArray(include);
|
|
248
|
+
const hasExplicitInclude = normalizedInclude.length > 0;
|
|
249
|
+
if (hasExplicitInclude) {
|
|
250
|
+
return {
|
|
251
|
+
include: dedupe(normalizedInclude),
|
|
252
|
+
discoveredDependencyDirectories: [],
|
|
253
|
+
hasExplicitInclude,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
const discoveredDependencyDirectories = discoverStylexPackageDirectories({
|
|
257
|
+
cwd,
|
|
258
|
+
importSources: importSources.filter((s) => typeof s === 'string' || typeof s === 'object'),
|
|
259
|
+
});
|
|
260
|
+
const discoveredDependencyGlobs = discoveredDependencyDirectories.map((dir) => toAbsoluteGlob(dir, exports.DEFAULT_INCLUDE_GLOB));
|
|
261
|
+
return {
|
|
262
|
+
include: dedupe([exports.DEFAULT_INCLUDE_GLOB, ...discoveredDependencyGlobs]),
|
|
263
|
+
discoveredDependencyDirectories,
|
|
264
|
+
hasExplicitInclude,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function resolveInclude({ cwd, include, importSources, }) {
|
|
268
|
+
return resolveIncludeWithMetadata({ cwd, include, importSources }).include;
|
|
269
|
+
}
|
|
270
|
+
function resolveExclude({ include, exclude, }) {
|
|
271
|
+
const normalizedExclude = toArray(exclude);
|
|
272
|
+
const hasExplicitInclude = toArray(include).length > 0;
|
|
273
|
+
if (hasExplicitInclude) {
|
|
274
|
+
return normalizedExclude;
|
|
275
|
+
}
|
|
276
|
+
return dedupe([...exports.AUTO_DISCOVERY_EXCLUDES, ...normalizedExclude]);
|
|
277
|
+
}
|