22 * Step: emit stylex.create objects and resolver imports.
33 * Core concepts: style emission and import aliasing.
44 */
5- import { basename } from "node:path" ;
5+ import { basename , dirname , join , relative , sep } from "node:path" ;
6+ import type { ImportSource } from "../../adapter.js" ;
67import { emitStylesAndImports } from "../emit-styles.js" ;
78import { CONTINUE , type StepResult } from "../transform-types.js" ;
89import { TransformContext } from "../transform-context.js" ;
@@ -112,9 +113,17 @@ function emitDefineMarkerDeclarations(
112113 . join ( "\n" ) ;
113114 ctx . sidecarStylexContent = `import * as stylex from "@stylexjs/stylex";\n\n${ markerDecls } \n` ;
114115
115- // Derive sidecar import path from file basename
116- const fileBase = basename ( ctx . file . path ) . replace ( / \. \w + $ / , "" ) ;
117- const sidecarImportPath = `./${ fileBase } .stylex` ;
116+ // Determine sidecar import path — use adapter.markerFile if provided, otherwise derive from basename
117+ let sidecarImportPath : string ;
118+ const adapterMarkerFile = ctx . adapter . markerFile ;
119+ if ( adapterMarkerFile ) {
120+ const importSource = adapterMarkerFile ( { filePath : ctx . file . path } ) ;
121+ sidecarImportPath = importSourceToModuleSpecifier ( importSource , ctx . file . path ) ;
122+ ctx . sidecarFilePath = importSourceToAbsolutePath ( importSource , ctx . file . path ) ;
123+ } else {
124+ const fileBase = basename ( ctx . file . path ) . replace ( / \. \w + $ / , "" ) ;
125+ sidecarImportPath = `./${ fileBase } .stylex` ;
126+ }
118127
119128 // Insert `import { XMarker, ... } from "./file.stylex"` after existing imports
120129 const importDecl = j . importDeclaration (
@@ -131,3 +140,33 @@ function emitDefineMarkerDeclarations(
131140 const insertAt = lastImportIdx >= 0 ? lastImportIdx + 1 : 0 ;
132141 programBody . splice ( insertAt , 0 , importDecl as unknown as { type ?: string } ) ;
133142}
143+
144+ /** Convert an ImportSource to a module specifier string for use in import declarations. */
145+ function importSourceToModuleSpecifier ( source : ImportSource , filePath : string ) : string {
146+ if ( source . kind === "specifier" ) {
147+ return source . value ;
148+ }
149+ // absolutePath → relative module specifier from current file
150+ const baseDir = dirname ( filePath ) ;
151+ let rel = relative ( baseDir , source . value ) . split ( sep ) . join ( "/" ) ;
152+ // Strip .ts/.tsx extension for module specifier
153+ rel = rel . replace ( / \. t s x ? $ / , "" ) ;
154+ if ( ! rel . startsWith ( "." ) ) {
155+ rel = `./${ rel } ` ;
156+ }
157+ return rel ;
158+ }
159+
160+ /** Resolve an ImportSource to an absolute file path for writing the sidecar file. */
161+ function importSourceToAbsolutePath ( source : ImportSource , filePath : string ) : string {
162+ if ( source . kind === "absolutePath" ) {
163+ return source . value ;
164+ }
165+ // specifier → resolve relative to source file directory, append .ts if no real file extension
166+ const baseDir = dirname ( filePath ) ;
167+ let resolved = join ( baseDir , source . value ) ;
168+ if ( ! / \. [ j t ] s x ? $ / . test ( resolved ) ) {
169+ resolved += ".ts" ;
170+ }
171+ return resolved ;
172+ }
0 commit comments