@@ -1792,7 +1792,7 @@ export class FormatPrinter extends Printer {
17921792 }
17931793 }
17941794
1795- const match = trimmedText . match ( / ^ [ . ! ? : ; ] + / )
1795+ const match = trimmedText . match ( / ^ [ . ! ? : ; % ] + / )
17961796
17971797 if ( ! match ) {
17981798 return {
@@ -1899,7 +1899,7 @@ export class FormatPrinter extends Printer {
18991899 if ( isNode ( child , HTMLTextNode ) ) {
19001900 const trimmed = child . content . trim ( )
19011901
1902- if ( trimmed && / ^ [ . ! ? : ; ] / . test ( trimmed ) ) {
1902+ if ( trimmed && / ^ [ . ! ? : ; % ] / . test ( trimmed ) ) {
19031903 const wrapWidth = this . maxLineLength - this . indent . length
19041904 const result = this . tryMergePunctuationText ( inlineContent , trimmed , wrapWidth )
19051905
@@ -1963,22 +1963,180 @@ export class FormatPrinter extends Printer {
19631963 } ) . join ( "" )
19641964 }
19651965
1966+ /**
1967+ * Count adjacent inline elements starting from a specific index
1968+ * Skips indices that are already processed
1969+ */
1970+ private countAdjacentInlineElementsFromIndex (
1971+ children : Node [ ] ,
1972+ startIndex : number ,
1973+ processedIndices : Set < number >
1974+ ) : number {
1975+ let count = 0
1976+ let lastSignificantIndex = - 1
1977+
1978+ for ( let i = startIndex ; i < children . length ; i ++ ) {
1979+ const child = children [ i ]
1980+
1981+ if ( isPureWhitespaceNode ( child ) || isNode ( child , WhitespaceNode ) ) {
1982+ continue
1983+ }
1984+
1985+ if ( processedIndices . has ( i ) ) {
1986+ break
1987+ }
1988+
1989+ const isInlineOrERB =
1990+ ( isNode ( child , HTMLElementNode ) && isInlineElement ( getTagName ( child ) ) ) ||
1991+ isNode ( child , ERBContentNode )
1992+
1993+ if ( ! isInlineOrERB ) {
1994+ break
1995+ }
1996+
1997+ if ( lastSignificantIndex >= 0 && hasWhitespaceBetween ( children , lastSignificantIndex , i ) ) {
1998+ break
1999+ }
2000+
2001+ count ++
2002+ lastSignificantIndex = i
2003+ }
2004+
2005+ return count
2006+ }
2007+
2008+ /**
2009+ * Render adjacent inline elements starting from a specific index
2010+ * Similar to renderAdjacentInlineElements but works from an arbitrary start point
2011+ */
2012+ private renderAdjacentInlineElementsFromIndex (
2013+ children : Node [ ] ,
2014+ startIndex : number ,
2015+ count : number ,
2016+ alreadyProcessed : Set < number >
2017+ ) : { processedIndices : Set < number > ; lastIndex : number } {
2018+ let inlineContent = ""
2019+ let processedCount = 0
2020+ let lastProcessedIndex = - 1
2021+ const processedIndices = new Set < number > ( )
2022+
2023+ for ( let index = startIndex ; index < children . length && processedCount < count ; index ++ ) {
2024+ const child = children [ index ]
2025+
2026+ if ( isPureWhitespaceNode ( child ) || isNode ( child , WhitespaceNode ) ) {
2027+ continue
2028+ }
2029+
2030+ if ( alreadyProcessed . has ( index ) ) {
2031+ continue
2032+ }
2033+
2034+ if ( isNode ( child , HTMLElementNode ) && isInlineElement ( getTagName ( child ) ) ) {
2035+ inlineContent += this . renderInlineElementAsString ( child )
2036+ processedCount ++
2037+ lastProcessedIndex = index
2038+ processedIndices . add ( index )
2039+
2040+ if ( inlineContent && isLineBreakingElement ( child ) ) {
2041+ this . pushWithIndent ( inlineContent )
2042+ inlineContent = ""
2043+ }
2044+ } else if ( isNode ( child , ERBContentNode ) ) {
2045+ inlineContent += this . renderERBAsString ( child )
2046+ processedCount ++
2047+ lastProcessedIndex = index
2048+ processedIndices . add ( index )
2049+ }
2050+ }
2051+
2052+ if ( lastProcessedIndex >= 0 ) {
2053+ for ( let index = lastProcessedIndex + 1 ; index < children . length ; index ++ ) {
2054+ const child = children [ index ]
2055+
2056+ if ( isPureWhitespaceNode ( child ) || isNode ( child , WhitespaceNode ) ) {
2057+ continue
2058+ }
2059+
2060+ if ( alreadyProcessed . has ( index ) ) {
2061+ break
2062+ }
2063+
2064+ if ( isNode ( child , ERBContentNode ) ) {
2065+ inlineContent += this . renderERBAsString ( child )
2066+ processedIndices . add ( index )
2067+ lastProcessedIndex = index
2068+ continue
2069+ }
2070+
2071+ if ( isNode ( child , HTMLTextNode ) ) {
2072+ const trimmed = child . content . trim ( )
2073+
2074+ if ( trimmed && / ^ [ . ! ? : ; % ] / . test ( trimmed ) ) {
2075+ const wrapWidth = this . maxLineLength - this . indent . length
2076+ const result = this . tryMergePunctuationText ( inlineContent , trimmed , wrapWidth )
2077+
2078+ inlineContent = result . mergedContent
2079+ processedIndices . add ( index )
2080+ lastProcessedIndex = index
2081+
2082+ if ( result . shouldStop ) {
2083+ if ( inlineContent ) {
2084+ this . pushWithIndent ( inlineContent )
2085+ }
2086+
2087+ result . wrappedLines . forEach ( line => this . push ( line ) )
2088+
2089+ return { processedIndices, lastIndex : lastProcessedIndex }
2090+ }
2091+ }
2092+ }
2093+
2094+ break
2095+ }
2096+ }
2097+
2098+ if ( inlineContent ) {
2099+ this . pushWithIndent ( inlineContent )
2100+ }
2101+
2102+ return {
2103+ processedIndices,
2104+ lastIndex : lastProcessedIndex >= 0 ? lastProcessedIndex : startIndex + count - 1
2105+ }
2106+ }
2107+
19662108 /**
19672109 * Visit remaining children after processing adjacent inline elements
2110+ * Recursively handles groups of adjacent inline elements
19682111 */
19692112 private visitRemainingChildren ( children : Node [ ] , processedIndices : Set < number > ) : void {
1970- for ( let index = 0 ; index < children . length ; index ++ ) {
2113+ let index = 0
2114+
2115+ while ( index < children . length ) {
19712116 const child = children [ index ]
19722117
19732118 if ( isPureWhitespaceNode ( child ) || isNode ( child , WhitespaceNode ) ) {
2119+ index ++
19742120 continue
19752121 }
19762122
19772123 if ( processedIndices . has ( index ) ) {
2124+ index ++
19782125 continue
19792126 }
19802127
1981- this . visit ( child )
2128+ const adjacentCount = this . countAdjacentInlineElementsFromIndex ( children , index , processedIndices )
2129+
2130+ if ( adjacentCount >= 2 ) {
2131+ const { processedIndices : newProcessedIndices , lastIndex } =
2132+ this . renderAdjacentInlineElementsFromIndex ( children , index , adjacentCount , processedIndices )
2133+
2134+ newProcessedIndices . forEach ( i => processedIndices . add ( i ) )
2135+ index = lastIndex + 1
2136+ } else {
2137+ this . visit ( child )
2138+ index ++
2139+ }
19822140 }
19832141 }
19842142
0 commit comments