@@ -6961,22 +6961,51 @@ fn gen_comment(comment: &Comment, context: &mut Context) -> Option<PrintItems> {
69616961fn gen_js_doc_or_multiline_block ( comment : & Comment , _context : & mut Context ) -> PrintItems {
69626962 debug_assert_eq ! ( comment. kind, CommentKind :: Block ) ;
69636963 let is_js_doc = comment. text . starts_with ( '*' ) ;
6964- return lines_to_print_items ( is_js_doc, build_lines ( comment) ) ;
6965-
6966- fn build_lines ( comment : & Comment ) -> Vec < & str > {
6967- let mut lines: Vec < & str > = Vec :: new ( ) ;
6964+ return lines_to_print_items ( is_js_doc, build_lines ( comment, is_js_doc) ) ;
6965+
6966+ fn build_lines ( comment : & Comment , is_js_doc : bool ) -> Vec < String > {
6967+ let mut lines: Vec < String > = Vec :: new ( ) ;
6968+ let raw_lines = utils:: split_lines ( & comment. text )
6969+ . map ( |line| {
6970+ let text = if line. line_index == 0 && !line. text . starts_with ( '*' ) {
6971+ line. text
6972+ } else {
6973+ & line. text [ get_line_start_index ( line. text ) ..]
6974+ } ;
6975+ ( text, line. is_last )
6976+ } )
6977+ . collect :: < Vec < _ > > ( ) ;
6978+ let mut fence_marker = None ;
69686979
6969- for line in utils:: split_lines ( & comment. text ) {
6970- let text = if line. line_index == 0 && !line. text . starts_with ( '*' ) {
6971- line. text
6980+ for ( index, ( text, is_last) ) in raw_lines. iter ( ) . enumerate ( ) {
6981+ let has_following_non_empty_line = raw_lines
6982+ . iter ( )
6983+ . skip ( index + 1 )
6984+ . any ( |( text, _) | !text. trim ( ) . is_empty ( ) ) ;
6985+ let line_fence_marker = get_markdown_fence_marker ( text) ;
6986+ let preserve_hard_break = is_js_doc
6987+ && fence_marker. is_none ( )
6988+ && line_fence_marker. is_none ( )
6989+ && has_following_non_empty_line
6990+ && !is_markdown_indented_code_line ( text) ;
6991+ let text = * text;
6992+ let text = if * is_last && !text. trim ( ) . is_empty ( ) {
6993+ text. to_string ( )
69726994 } else {
6973- & line . text [ get_line_start_index ( line . text ) .. ]
6995+ trim_end_preserving_markdown_hard_break ( text, preserve_hard_break )
69746996 } ;
6975- let text = if line. is_last && !text. trim ( ) . is_empty ( ) { text } else { text. trim_end ( ) } ;
69766997
69776998 if !text. is_empty ( ) || !lines. last ( ) . map ( |l| l. is_empty ( ) ) . unwrap_or ( false ) {
69786999 lines. push ( text) ;
69797000 }
7001+
7002+ if let Some ( marker) = line_fence_marker {
7003+ fence_marker = match fence_marker {
7004+ Some ( current_marker) if current_marker == marker => None ,
7005+ Some ( current_marker) => Some ( current_marker) ,
7006+ None => Some ( marker) ,
7007+ } ;
7008+ }
69807009 }
69817010
69827011 lines
@@ -6994,7 +7023,40 @@ fn gen_js_doc_or_multiline_block(comment: &Comment, _context: &mut Context) -> P
69947023 0
69957024 }
69967025
6997- fn lines_to_print_items ( is_js_doc : bool , lines : Vec < & str > ) -> PrintItems {
7026+ fn get_markdown_fence_marker ( text : & str ) -> Option < char > {
7027+ let text = text. trim_start ( ) ;
7028+ let marker = text. chars ( ) . next ( ) ?;
7029+ if marker != '`' && marker != '~' {
7030+ return None ;
7031+ }
7032+ if text. chars ( ) . take_while ( |& c| c == marker) . count ( ) >= 3 {
7033+ Some ( marker)
7034+ } else {
7035+ None
7036+ }
7037+ }
7038+
7039+ fn is_markdown_indented_code_line ( text : & str ) -> bool {
7040+ let text = text. strip_prefix ( ' ' ) . unwrap_or ( text) ;
7041+ text. starts_with ( " " ) || text. starts_with ( '\t' )
7042+ }
7043+
7044+ fn trim_end_preserving_markdown_hard_break ( text : & str , preserve_hard_break : bool ) -> String {
7045+ let trimmed = text. trim_end ( ) ;
7046+ let trailing_space_count = text
7047+ . as_bytes ( )
7048+ . iter ( )
7049+ . rev ( )
7050+ . take_while ( |& & byte| byte == b' ' )
7051+ . count ( ) ;
7052+ if preserve_hard_break && trailing_space_count >= 2 && !trimmed. is_empty ( ) {
7053+ format ! ( "{trimmed}\\ " )
7054+ } else {
7055+ trimmed. to_string ( )
7056+ }
7057+ }
7058+
7059+ fn lines_to_print_items ( is_js_doc : bool , lines : Vec < String > ) -> PrintItems {
69987060 let mut items = PrintItems :: new ( ) ;
69997061
70007062 items. push_sc ( sc ! ( "/*" ) ) ;
0 commit comments