@@ -10,15 +10,15 @@ const CBK: &[u8] = b"```";
1010const CIL : & [ u8 ] = b"`" ;
1111const CMT_E : & [ u8 ] = b"-->" ;
1212const CMT_S : & [ u8 ] = b"<!--" ;
13- const EMP : & [ u8 ] = b"_" ;
13+ const EMP_U : & [ u8 ] = b"_" ;
14+ const EMP_A : & [ u8 ] = b"*" ;
1415const HDG : & [ u8 ] = b"#" ;
1516const LNK_CHARS : & str = "$-_.+!*'()/&?=:%" ;
1617const LNK_E : & [ u8 ] = b"]" ;
1718const LNK_S : & [ u8 ] = b"[" ;
18- const STG : & [ u8 ] = b"**" ;
19+ const STG_U : & [ u8 ] = b"__" ;
20+ const STG_A : & [ u8 ] = b"**" ;
1921const STK : & [ u8 ] = b"~~" ;
20- const UL1 : & [ u8 ] = b"* " ;
21- const UL2 : & [ u8 ] = b"- " ;
2222
2323/// Pattern replacements
2424const REPLACEMENTS : & [ ( & str , & str ) ] = & [
@@ -100,22 +100,29 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
100100 } ;
101101
102102 let res: ParseResult < ' _ > = match ( top_blk, prev) {
103- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( CMT_S ) => {
103+ _ if loop_buf. starts_with ( CMT_S ) => {
104104 parse_simple_pat ( loop_buf, CMT_S , CMT_E , Po :: TrimNoEsc , MdTree :: Comment )
105105 }
106106 ( true , Newline ) if loop_buf. starts_with ( CBK ) => Some ( parse_codeblock ( loop_buf) ) ,
107- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( CIL ) => parse_codeinline ( loop_buf) ,
107+ _ if loop_buf. starts_with ( CIL ) => parse_codeinline ( loop_buf) ,
108108 ( true , Newline | Whitespace ) if loop_buf. starts_with ( HDG ) => parse_heading ( loop_buf) ,
109109 ( true , Newline ) if loop_buf. starts_with ( BRK ) => {
110110 Some ( ( MdTree :: HorizontalRule , parse_to_newline ( loop_buf) . 1 ) )
111111 }
112- ( _, Newline | Whitespace ) if loop_buf. starts_with ( EMP ) => {
113- parse_simple_pat ( loop_buf, EMP , EMP , Po :: None , MdTree :: Emphasis )
112+ ( _, Newline ) if unordered_list_start ( loop_buf) => Some ( parse_unordered_li ( loop_buf) ) ,
113+ ( _, Newline | Whitespace ) if loop_buf. starts_with ( STG_U ) => {
114+ parse_simple_pat ( loop_buf, STG_U , STG_U , Po :: None , MdTree :: Strong )
114115 }
115- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( STG ) => {
116- parse_simple_pat ( loop_buf, STG , STG , Po :: None , MdTree :: Strong )
116+ _ if loop_buf. starts_with ( STG_A ) => {
117+ parse_simple_pat ( loop_buf, STG_A , STG_A , Po :: None , MdTree :: Strong )
117118 }
118- ( _, Newline | Whitespace ) if loop_buf. starts_with ( STK ) => {
119+ ( _, Newline | Whitespace ) if loop_buf. starts_with ( EMP_U ) => {
120+ parse_simple_pat ( loop_buf, EMP_U , EMP_U , Po :: None , MdTree :: Emphasis )
121+ }
122+ _ if loop_buf. starts_with ( EMP_A ) => {
123+ parse_simple_pat ( loop_buf, EMP_A , EMP_A , Po :: None , MdTree :: Emphasis )
124+ }
125+ _ if loop_buf. starts_with ( STK ) => {
119126 parse_simple_pat ( loop_buf, STK , STK , Po :: None , MdTree :: Strikethrough )
120127 }
121128 ( _, Newline | Whitespace ) if loop_buf. starts_with ( ANC_S ) => {
@@ -130,11 +137,8 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
130137 _ => None ,
131138 }
132139 }
133- ( _, Newline ) if ( loop_buf. starts_with ( UL1 ) || loop_buf. starts_with ( UL2 ) ) => {
134- Some ( parse_unordered_li ( loop_buf) )
135- }
136140 ( _, Newline ) if ord_list_start ( loop_buf) . is_some ( ) => Some ( parse_ordered_li ( loop_buf) ) ,
137- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( LNK_S ) => {
141+ _ if loop_buf. starts_with ( LNK_S ) => {
138142 parse_any_link ( loop_buf, top_blk && prev == Prev :: Newline )
139143 }
140144 ( _, Escape | _) => None ,
@@ -251,7 +255,6 @@ fn parse_heading(buf: &[u8]) -> ParseResult<'_> {
251255
252256/// Bulleted list
253257fn parse_unordered_li ( buf : & [ u8 ] ) -> Parsed < ' _ > {
254- debug_assert ! ( buf. starts_with( b"* " ) || buf. starts_with( b"- " ) ) ;
255258 let ( txt, rest) = get_indented_section ( & buf[ 2 ..] ) ;
256259 let ctx = Context { top_block : false , prev : Prev :: Whitespace } ;
257260 let stream = parse_recursive ( trim_ascii_start ( txt) , ctx) ;
@@ -267,25 +270,28 @@ fn parse_ordered_li(buf: &[u8]) -> Parsed<'_> {
267270 ( MdTree :: OrderedListItem ( num, stream) , rest)
268271}
269272
270- /// Find first line that isn't empty or doesn't start with whitespace, that will
271- /// be our contents
272273fn get_indented_section ( buf : & [ u8 ] ) -> ( & [ u8 ] , & [ u8 ] ) {
273- let mut end = buf. len ( ) ;
274- for ( idx, window) in buf. windows ( 2 ) . enumerate ( ) {
275- let & [ ch, next_ch] = window else { unreachable ! ( "always 2 elements" ) } ;
276- if idx >= buf. len ( ) . saturating_sub ( 2 ) && next_ch == b'\n' {
277- // End of stream
278- end = buf. len ( ) . saturating_sub ( 1 ) ;
279- break ;
280- } else if ch == b'\n' && ( !next_ch. is_ascii_whitespace ( ) || next_ch == b'\n' ) {
281- end = idx;
282- break ;
274+ let mut lines = buf. split ( |& byte| byte == b'\n' ) ;
275+ let mut end = lines. next ( ) . map_or ( 0 , |line| line. len ( ) ) ;
276+ for line in lines {
277+ if let Some ( first) = line. first ( ) {
278+ if unordered_list_start ( line) || !first. is_ascii_whitespace ( ) {
279+ break ;
280+ }
283281 }
282+ end += line. len ( ) + 1 ;
284283 }
285284
286285 ( & buf[ ..end] , & buf[ end..] )
287286}
288287
288+ fn unordered_list_start ( mut buf : & [ u8 ] ) -> bool {
289+ while let [ b' ' , rest @ ..] = buf {
290+ buf = rest;
291+ }
292+ matches ! ( buf, [ b'*' | b'-' , b' ' , ..] )
293+ }
294+
289295/// Verify a valid ordered list start (e.g. `1.`) and parse it. Returns the
290296/// parsed number and offset of character after the dot.
291297fn ord_list_start ( buf : & [ u8 ] ) -> Option < ( u16 , usize ) > {
0 commit comments