@@ -100,6 +100,116 @@ impl<'text> MagicString<'text> {
100100 self . source . len ( ) != self . len ( ) || self . source . as_ref ( ) != self . to_string ( )
101101 }
102102
103+ /// Returns the last character of the generated string, or `None` if empty.
104+ pub fn last_char ( & self ) -> Option < char > {
105+ // Check outro first (last in output order)
106+ if let Some ( last_outro) = self . outro . back ( ) {
107+ if let Some ( c) = last_outro. chars ( ) . last ( ) {
108+ return Some ( c) ;
109+ }
110+ }
111+
112+ // Traverse chunks from last to first
113+ let mut chunk_idx = Some ( self . last_chunk_idx ) ;
114+ while let Some ( idx) = chunk_idx {
115+ let chunk = & self . chunks [ idx] ;
116+
117+ // Check chunk outro
118+ if let Some ( last_outro) = chunk. outro . back ( ) {
119+ if let Some ( c) = last_outro. chars ( ) . last ( ) {
120+ return Some ( c) ;
121+ }
122+ }
123+
124+ // Check chunk content (edited or original)
125+ let content = chunk
126+ . edited_content
127+ . as_ref ( )
128+ . map ( |s| s. as_ref ( ) )
129+ . unwrap_or_else ( || chunk. span . text ( & self . source ) ) ;
130+ if let Some ( c) = content. chars ( ) . last ( ) {
131+ return Some ( c) ;
132+ }
133+
134+ // Check chunk intro
135+ if let Some ( last_intro) = chunk. intro . back ( ) {
136+ if let Some ( c) = last_intro. chars ( ) . last ( ) {
137+ return Some ( c) ;
138+ }
139+ }
140+
141+ chunk_idx = chunk. prev ;
142+ }
143+
144+ // Check intro last (first in output order, but we're going backwards)
145+ if let Some ( last_intro) = self . intro . back ( ) {
146+ if let Some ( c) = last_intro. chars ( ) . last ( ) {
147+ return Some ( c) ;
148+ }
149+ }
150+
151+ None
152+ }
153+
154+ /// Returns the content after the last newline in the generated string.
155+ pub fn last_line ( & self ) -> String {
156+ // Check outro first (last in output order)
157+ for outro_part in self . outro . iter ( ) . rev ( ) {
158+ if let Some ( line_index) = memchr:: memrchr ( b'\n' , outro_part. as_bytes ( ) ) {
159+ return outro_part[ line_index + 1 ..] . to_string ( ) ;
160+ }
161+ }
162+
163+ let mut line_str = self . outro . iter ( ) . map ( |s| s. as_ref ( ) ) . collect :: < String > ( ) ;
164+
165+ // Traverse chunks from last to first
166+ let mut chunk_idx = Some ( self . last_chunk_idx ) ;
167+ while let Some ( idx) = chunk_idx {
168+ let chunk = & self . chunks [ idx] ;
169+
170+ // Check chunk outro
171+ for outro_part in chunk. outro . iter ( ) . rev ( ) {
172+ if let Some ( line_index) = memchr:: memrchr ( b'\n' , outro_part. as_bytes ( ) ) {
173+ return outro_part[ line_index + 1 ..] . to_string ( ) + & line_str;
174+ }
175+ }
176+ let chunk_outro: String = chunk. outro . iter ( ) . map ( |s| s. as_ref ( ) ) . collect ( ) ;
177+ line_str = chunk_outro + & line_str;
178+
179+ // Check chunk content (edited or original)
180+ let content = chunk
181+ . edited_content
182+ . as_ref ( )
183+ . map ( |s| s. as_ref ( ) )
184+ . unwrap_or_else ( || chunk. span . text ( & self . source ) ) ;
185+ if let Some ( line_index) = memchr:: memrchr ( b'\n' , content. as_bytes ( ) ) {
186+ return content[ line_index + 1 ..] . to_string ( ) + & line_str;
187+ }
188+ line_str = content. to_string ( ) + & line_str;
189+
190+ // Check chunk intro
191+ for intro_part in chunk. intro . iter ( ) . rev ( ) {
192+ if let Some ( line_index) = memchr:: memrchr ( b'\n' , intro_part. as_bytes ( ) ) {
193+ return intro_part[ line_index + 1 ..] . to_string ( ) + & line_str;
194+ }
195+ }
196+ let chunk_intro: String = chunk. intro . iter ( ) . map ( |s| s. as_ref ( ) ) . collect ( ) ;
197+ line_str = chunk_intro + & line_str;
198+
199+ chunk_idx = chunk. prev ;
200+ }
201+
202+ // Check intro last (first in output order, but we're going backwards)
203+ for intro_part in self . intro . iter ( ) . rev ( ) {
204+ if let Some ( line_index) = memchr:: memrchr ( b'\n' , intro_part. as_bytes ( ) ) {
205+ return intro_part[ line_index + 1 ..] . to_string ( ) + & line_str;
206+ }
207+ }
208+
209+ let intro_str: String = self . intro . iter ( ) . map ( |s| s. as_ref ( ) ) . collect ( ) ;
210+ intro_str + & line_str
211+ }
212+
103213 fn prepend_intro ( & mut self , content : impl Into < CowStr < ' text > > ) {
104214 self . intro . push_front ( content. into ( ) ) ;
105215 }
0 commit comments