@@ -13,7 +13,6 @@ import { dirname, join } from 'node:path';
1313import { promisify } from 'node:util' ;
1414
1515const execFileAsync = promisify ( execFile ) ;
16- let prettierCliPath : string | null | undefined ;
1716
1817/**
1918 * Conservative upper bound for the length of a single spawned command line.
@@ -60,7 +59,7 @@ export function batchFilesByArgumentLength(
6059}
6160
6261/**
63- * Formats files using Prettier.
62+ * Formats files using the workspace's Oxfmt or Prettier installation .
6463 * @param cwd The current working directory.
6564 * @param files The files to format.
6665 */
@@ -69,40 +68,44 @@ export async function formatFiles(cwd: string, files: Set<string>): Promise<void
6968 return ;
7069 }
7170
72- if ( prettierCliPath === undefined ) {
71+ const workspaceRequire = createRequire ( cwd + '/' ) ;
72+ let formatterCliPath : string | undefined ;
73+ let formatter : string | undefined ;
74+ for ( const name of [ 'oxfmt' , 'prettier' ] ) {
75+ let packageJsonPath : string ;
7376 try {
74- const prettierPath = createRequire ( cwd + '/' ) . resolve ( 'prettier/package.json' ) ;
75- const prettierPackageJson = JSON . parse ( await readFile ( prettierPath , 'utf-8' ) ) as {
76- bin : string ;
77- } ;
78- prettierCliPath = join ( dirname ( prettierPath ) , prettierPackageJson . bin ) ;
77+ packageJsonPath = workspaceRequire . resolve ( `${ name } /package.json` ) ;
7978 } catch {
80- // Prettier is not installed.
81- prettierCliPath = null ;
79+ continue ;
8280 }
81+
82+ const { bin } = JSON . parse ( await readFile ( packageJsonPath , 'utf-8' ) ) as {
83+ bin : string | Record < string , string > ;
84+ } ;
85+ formatterCliPath = join ( dirname ( packageJsonPath ) , typeof bin === 'string' ? bin : bin [ name ] ) ;
86+ formatter = name ;
87+ break ;
8388 }
8489
85- if ( ! prettierCliPath ) {
90+ if ( ! formatterCliPath ) {
8691 return ;
8792 }
8893
89- const baseArgs = [
90- prettierCliPath ,
91- '--write' ,
92- '--no-error-on-unmatched-pattern' ,
93- '--ignore-unknown' ,
94- ] ;
94+ const baseArgs = [ formatterCliPath , '--write' , '--no-error-on-unmatched-pattern' ] ;
95+ if ( formatter === 'prettier' ) {
96+ baseArgs . push ( '--ignore-unknown' ) ;
97+ }
9598 // `process.execPath` is spawned as the first argument and also counts toward the
96- // command-line limit; it and `prettierCliPath ` are absolute paths that may contain
99+ // command-line limit; it and `formatterCliPath ` are absolute paths that may contain
97100 // spaces and therefore be quoted.
98101 const baseLength = [ process . execPath , ...baseArgs ] . reduce (
99102 ( total , arg ) => total + arg . length + ( arg . includes ( ' ' ) ? 3 : 1 ) ,
100103 0 ,
101104 ) ;
102105
103- // Spawn Prettier once per batch so repositories with many changed files do not
106+ // Spawn the formatter once per batch so repositories with many changed files do not
104107 // overflow the OS command-line length limit. A failure in one batch (e.g. a file
105- // Prettier cannot parse) must not stop the remaining batches, matching the previous
108+ // the formatter cannot parse) must not stop the remaining batches, matching the previous
106109 // single-invocation behavior, so errors are collected and reported together.
107110 const errors : string [ ] = [ ] ;
108111 for ( const batch of batchFilesByArgumentLength ( files , baseLength , MAX_COMMAND_LINE_LENGTH ) ) {
0 commit comments