Skip to content

Commit 7e3b37c

Browse files
committed
fix: move alias rewriting to babel plugin
1 parent 10e5495 commit 7e3b37c

File tree

4 files changed

+66
-152
lines changed

4 files changed

+66
-152
lines changed

packages/babel-plugin/src/index.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import type { NodePath } from '@babel/traverse';
1212
import type { PluginObj } from '@babel/core';
1313
import type { StyleXOptions } from './utils/state-manager';
1414
import StateManager from './utils/state-manager';
15+
import {
16+
EXTENSIONS,
17+
filePathResolver,
18+
matchesFileSuffix,
19+
getRelativePath,
20+
} from './utils/state-manager';
1521
import { readImportDeclarations, readRequires } from './visitors/imports';
1622
import transformStyleXCreate from './visitors/stylex-create';
1723
import transformStyleXDefineVars from './visitors/stylex-define-vars';
@@ -74,6 +80,44 @@ function styleXTransform(): PluginObj<> {
7480
// variables entirely if they're not needed.
7581
exit: (path: NodePath<t.Program>) => {
7682
path.traverse({
83+
ImportDeclaration(path: NodePath<t.ImportDeclaration>) {
84+
const filename = state.filename;
85+
if (filename == null || !state.options.rewriteAliases) {
86+
return;
87+
}
88+
89+
const source = path.node.source.value;
90+
91+
const aliases = state.options.aliases;
92+
93+
const themeFileExtension = '.stylex';
94+
if (!matchesFileSuffix(themeFileExtension)(source)) {
95+
return;
96+
}
97+
const resolvedFilePath = filePathResolver(
98+
source,
99+
filename,
100+
aliases,
101+
);
102+
103+
if (resolvedFilePath == null) {
104+
return;
105+
}
106+
107+
let relativeFilePath = getRelativePath(
108+
filename,
109+
resolvedFilePath,
110+
);
111+
112+
const extension = EXTENSIONS.find((ext) =>
113+
relativeFilePath.endsWith(ext),
114+
);
115+
if (extension != null) {
116+
relativeFilePath = relativeFilePath.slice(0, -extension.length);
117+
}
118+
119+
path.node.source.value = relativeFilePath;
120+
},
77121
Identifier(path: NodePath<t.Identifier>) {
78122
// Look for variables bound to `stylex.create` calls that are used
79123
// outside of `stylex(...)` calls

packages/babel-plugin/src/utils/state-manager.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,15 @@ export type StyleXOptions = $ReadOnly<{
7878
genConditionalClasses: boolean,
7979
unstable_moduleResolution?: ?ModuleResolution,
8080
aliases?: ?$ReadOnly<{ [string]: string | $ReadOnlyArray<string> }>,
81+
rewriteAliases?: boolean,
8182
...
8283
}>;
8384

8485
type StyleXStateOptions = $ReadOnly<{
8586
...StyleXOptions,
8687
runtimeInjection: ?string | $ReadOnly<{ from: string, as: ?string }>,
8788
aliases?: ?$ReadOnly<{ [string]: $ReadOnlyArray<string> }>,
89+
rewriteAliases: boolean,
8890
...
8991
}>;
9092

@@ -289,6 +291,10 @@ export default class StateManager {
289291
styleResolution,
290292
unstable_moduleResolution,
291293
treeshakeCompensation,
294+
rewriteAliases:
295+
typeof options.rewriteAliases === 'boolean'
296+
? options.rewriteAliases
297+
: false,
292298
};
293299
return opts;
294300
}
@@ -694,7 +700,7 @@ export const filePathResolver = (
694700
return null;
695701
};
696702

697-
const EXTENSIONS = ['.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs'];
703+
export const EXTENSIONS = ['.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs'];
698704

699705
const addFileExtension = (
700706
importedFilePath: string,
@@ -744,3 +750,16 @@ const getProgramStatement = (path: NodePath<>): NodePath<> => {
744750
}
745751
return programPath;
746752
};
753+
754+
export function getRelativePath(from: string, to: string): string {
755+
const relativePath = path.relative(path.parse(from).dir, to);
756+
return formatRelativePath(toPosixPath(relativePath));
757+
}
758+
759+
function toPosixPath(filePath: string): string {
760+
return filePath.split(path.sep).join(path.posix.sep);
761+
}
762+
763+
function formatRelativePath(filePath: string) {
764+
return filePath.startsWith('.') ? filePath : './' + filePath;
765+
}

packages/cli/src/plugins.js

Lines changed: 0 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import type { NodePath } from '@babel/traverse';
1212
import { getRelativePath } from './files';
1313
import { findModuleDir } from './modules';
1414
import * as t from '@babel/types';
15-
import { moduleResolve } from '@dual-bundle/import-meta-resolve';
16-
import url from 'url';
1715

1816
import * as nodePath from 'path';
1917

@@ -121,143 +119,3 @@ export const createModuleImportModifierPlugin = (
121119
},
122120
};
123121
};
124-
125-
export const createAliasRewritePlugin = (
126-
sourceFilePath: string,
127-
aliasConfig: $ReadOnly<{ [string]: string | $ReadOnlyArray<string> }>,
128-
): ImportModifierPlugin => {
129-
return {
130-
visitor: {
131-
Program: {
132-
exit(path: NodePath<t.Program>) {
133-
path.traverse({
134-
ImportDeclaration: {
135-
enter(path: NodePath<t.ImportDeclaration>) {
136-
const source = path.node.source.value;
137-
138-
const aliases =
139-
aliasConfig == null
140-
? aliasConfig
141-
: Object.fromEntries(
142-
Object.entries(aliasConfig).map(([key, value]) => {
143-
if (typeof value === 'string') {
144-
return [key, [value]];
145-
}
146-
return [key, value];
147-
}),
148-
);
149-
150-
const themeFileExtension = '.stylex';
151-
if (!matchesFileSuffix(themeFileExtension)(source)) {
152-
return;
153-
}
154-
const resolvedFilePath = filePathResolver(
155-
source,
156-
sourceFilePath,
157-
aliases,
158-
);
159-
160-
if (resolvedFilePath == null) {
161-
return;
162-
}
163-
164-
let relativeFilePath = getRelativePath(
165-
sourceFilePath,
166-
resolvedFilePath,
167-
);
168-
169-
const extension = EXTENSIONS.find((ext) =>
170-
relativeFilePath.endsWith(ext),
171-
);
172-
if (extension != null) {
173-
relativeFilePath = relativeFilePath.slice(
174-
0,
175-
-extension.length,
176-
);
177-
}
178-
179-
path.node.source.value = relativeFilePath;
180-
},
181-
},
182-
});
183-
},
184-
},
185-
},
186-
};
187-
};
188-
189-
const matchesFileSuffix = (allowedSuffix: string) => (filename: string) =>
190-
filename.endsWith(`${allowedSuffix}.js`) ||
191-
filename.endsWith(`${allowedSuffix}.ts`) ||
192-
filename.endsWith(`${allowedSuffix}.tsx`) ||
193-
filename.endsWith(`${allowedSuffix}.jsx`) ||
194-
filename.endsWith(`${allowedSuffix}.mjs`) ||
195-
filename.endsWith(`${allowedSuffix}.cjs`) ||
196-
filename.endsWith(allowedSuffix);
197-
198-
const EXTENSIONS = ['.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs'];
199-
const filePathResolver = (
200-
relativeFilePath: string,
201-
sourceFilePath: string,
202-
aliases: $ReadOnly<{ [string]: $ReadOnlyArray<string> }>,
203-
): ?string => {
204-
// Try importing without adding any extension
205-
// and then every supported extension
206-
for (const ext of ['', ...EXTENSIONS]) {
207-
const importPathStr = relativeFilePath + ext;
208-
209-
// Try to resolve relative paths as is
210-
if (importPathStr.startsWith('.')) {
211-
try {
212-
return moduleResolve(importPathStr, url.pathToFileURL(sourceFilePath))
213-
.pathname;
214-
} catch {
215-
continue;
216-
}
217-
}
218-
219-
// Otherwise, try to resolve the path with aliases
220-
const allAliases = possibleAliasedPaths(importPathStr, aliases);
221-
for (const possiblePath of allAliases) {
222-
try {
223-
return moduleResolve(possiblePath, url.pathToFileURL(sourceFilePath))
224-
.pathname;
225-
} catch {
226-
continue;
227-
}
228-
}
229-
}
230-
// Failed to resolve the file path
231-
return null;
232-
};
233-
234-
function possibleAliasedPaths(
235-
importPath: string,
236-
aliases: $ReadOnly<{ [string]: $ReadOnlyArray<string> }>,
237-
): $ReadOnlyArray<string> {
238-
const result = [importPath];
239-
if (aliases == null || Object.keys(aliases).length === 0) {
240-
return result;
241-
}
242-
243-
for (const [alias, value] of Object.entries(aliases)) {
244-
if (alias.includes('*')) {
245-
const [before, after] = alias.split('*');
246-
if (importPath.startsWith(before) && importPath.endsWith(after)) {
247-
const replacementString = importPath.slice(
248-
before.length,
249-
after.length > 0 ? -after.length : undefined,
250-
);
251-
value.forEach((v) => {
252-
result.push(v.split('*').join(replacementString));
253-
});
254-
}
255-
} else if (alias === importPath) {
256-
value.forEach((v) => {
257-
result.push(v);
258-
});
259-
}
260-
}
261-
262-
return result;
263-
}

packages/cli/src/transform.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
getDefaultCachePath,
3232
} from './cache';
3333
import {
34-
createAliasRewritePlugin,
3534
createImportPlugin,
3635
createModuleImportModifierPlugin,
3736
} from './plugins';
@@ -156,8 +155,6 @@ export async function transformFile(
156155
: path.join(config.output, config.styleXBundleName),
157156
);
158157

159-
const aliases = config.styleXConfig?.aliases;
160-
161158
const result = await babel.transformFileAsync(inputFilePath, {
162159
babelrc: false,
163160
presets: config.babelPresets,
@@ -173,15 +170,11 @@ export async function transformFile(
173170
rootDir: path.parse(config.output).dir,
174171
},
175172
...(config.styleXConfig as $FlowFixMe),
173+
rewriteAliases: true,
176174
},
177175
],
178176
createImportPlugin(relativeImport),
179-
...[
180-
aliases != null
181-
? createAliasRewritePlugin(inputFilePath, aliases)
182-
: null,
183-
...(config.babelPluginsPost ?? []),
184-
].filter(Boolean),
177+
...(config.babelPluginsPost ?? []),
185178
],
186179
});
187180
if (result == null) {

0 commit comments

Comments
 (0)