66 * from the token stream, applying consistent formatting rules.
77 */
88import type { IToken } from "chevrotain" ;
9+ import type { CstNode } from "chevrotain" ;
910import { BridgeLexer } from "./parser/lexer.ts" ;
10-
11- const INDENT = " " ;
11+ import { parseBridgeCst } from "./parser/parser.ts" ;
12+
13+ const DEFAULT_FORMATTING_OPTIONS = {
14+ tabSize : 2 ,
15+ insertSpaces : true ,
16+ } as const ;
17+
18+ export type BridgeFormattingOptions = {
19+ tabSize : number ;
20+ insertSpaces : boolean ;
21+ } ;
22+
23+ function resolveFormattingOptions (
24+ options ?: Partial < BridgeFormattingOptions > ,
25+ ) : BridgeFormattingOptions {
26+ const rawTabSize = options ?. tabSize ;
27+ const tabSize =
28+ typeof rawTabSize === "number" && Number . isInteger ( rawTabSize )
29+ ? Math . max ( 1 , rawTabSize )
30+ : DEFAULT_FORMATTING_OPTIONS . tabSize ;
31+
32+ return {
33+ tabSize,
34+ insertSpaces : options ?. insertSpaces ?? DEFAULT_FORMATTING_OPTIONS . insertSpaces ,
35+ } ;
36+ }
1237
1338// ── Comment handling ─────────────────────────────────────────────────────────
1439
@@ -142,10 +167,29 @@ function isTopLevelBlockStart(group: IToken[]): boolean {
142167/**
143168 * Format Bridge DSL source code with consistent styling.
144169 *
145- * @param source - The Bridge DSL source text to format
146- * @returns Formatted source text, or the original if parsing fails
170+ * Throws on syntax-invalid input when called with a source string.
147171 */
148- export function formatBridge ( source : string ) : string {
172+ type PrettyPrintInput = string | { source : string ; cst : CstNode } ;
173+
174+ export function prettyPrintToSource (
175+ input : PrettyPrintInput ,
176+ options ?: Partial < BridgeFormattingOptions > ,
177+ ) : string {
178+ const source = typeof input === "string" ? input : input . source ;
179+ if ( typeof input === "string" ) {
180+ parseBridgeCst ( source ) ;
181+ }
182+ return formatBridgeInternal ( source , options ) ;
183+ }
184+
185+ function formatBridgeInternal (
186+ source : string ,
187+ options ?: Partial < BridgeFormattingOptions > ,
188+ ) : string {
189+ const formatting = resolveFormattingOptions ( options ) ;
190+ const indentUnit = formatting . insertSpaces
191+ ? " " . repeat ( formatting . tabSize )
192+ : "\t" ;
149193 const lexResult = BridgeLexer . tokenize ( source ) ;
150194
151195 if ( lexResult . errors . length > 0 ) {
@@ -313,7 +357,7 @@ export function formatBridge(source: string): string {
313357 if ( lastCommentLine > 0 && commentLine > lastCommentLine + 1 ) {
314358 output . push ( "\n" ) ; // Preserve blank line between comments
315359 }
316- output . push ( INDENT . repeat ( lineStartDepth ) + comment . image + "\n" ) ;
360+ output . push ( indentUnit . repeat ( lineStartDepth ) + comment . image + "\n" ) ;
317361 lastCommentLine = commentLine ;
318362 }
319363 }
@@ -371,7 +415,7 @@ export function formatBridge(source: string): string {
371415 ) ;
372416 if ( hasContentAfter && lineOutput . length > 0 ) {
373417 // Emit the line with the brace, content will continue on next iteration
374- output . push ( INDENT . repeat ( currentIndent ) + lineOutput + "\n" ) ;
418+ output . push ( indentUnit . repeat ( currentIndent ) + lineOutput + "\n" ) ;
375419 lineOutput = "" ;
376420 lastType = null ;
377421 currentIndent = depth ; // Update indentation for remaining content
@@ -390,7 +434,7 @@ export function formatBridge(source: string): string {
390434
391435 // Output anything accumulated first
392436 if ( lineOutput . length > 0 ) {
393- output . push ( INDENT . repeat ( depth ) + lineOutput + "\n" ) ;
437+ output . push ( indentUnit . repeat ( depth ) + lineOutput + "\n" ) ;
394438 lineOutput = "" ;
395439 }
396440 // Decrement depth, then emit brace at new (outer) depth
@@ -405,7 +449,7 @@ export function formatBridge(source: string): string {
405449 }
406450
407451 // Emit the closing brace immediately
408- output . push ( INDENT . repeat ( depth ) + braceOutput + "\n" ) ;
452+ output . push ( indentUnit . repeat ( depth ) + braceOutput + "\n" ) ;
409453 continue ;
410454 }
411455
@@ -458,7 +502,7 @@ export function formatBridge(source: string): string {
458502
459503 // Emit the line
460504 if ( lineOutput . length > 0 ) {
461- output . push ( INDENT . repeat ( currentIndent ) + lineOutput + "\n" ) ;
505+ output . push ( indentUnit . repeat ( currentIndent ) + lineOutput + "\n" ) ;
462506 }
463507
464508 lastOutputLine = originalLine ;
0 commit comments