@@ -10,15 +10,11 @@ const CBK: &[u8] = b"```";
1010const CIL : & [ u8 ] = b"`" ;
1111const CMT_E : & [ u8 ] = b"-->" ;
1212const CMT_S : & [ u8 ] = b"<!--" ;
13- const EMP : & [ u8 ] = b"_" ;
1413const HDG : & [ u8 ] = b"#" ;
1514const LNK_CHARS : & str = "$-_.+!*'()/&?=:%" ;
1615const LNK_E : & [ u8 ] = b"]" ;
1716const LNK_S : & [ u8 ] = b"[" ;
18- const STG : & [ u8 ] = b"**" ;
1917const STK : & [ u8 ] = b"~~" ;
20- const UL1 : & [ u8 ] = b"* " ;
21- const UL2 : & [ u8 ] = b"- " ;
2218
2319/// Pattern replacements
2420const REPLACEMENTS : & [ ( & str , & str ) ] = & [
@@ -100,25 +96,26 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
10096 } ;
10197
10298 let res: ParseResult < ' _ > = match ( top_blk, prev) {
103- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( CMT_S ) => {
99+ _ if loop_buf. starts_with ( CMT_S ) => {
104100 parse_simple_pat ( loop_buf, CMT_S , CMT_E , Po :: TrimNoEsc , MdTree :: Comment )
105101 }
106102 ( 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) ,
103+ _ if loop_buf. starts_with ( CIL ) => parse_codeinline ( loop_buf) ,
108104 ( true , Newline | Whitespace ) if loop_buf. starts_with ( HDG ) => parse_heading ( loop_buf) ,
109105 ( true , Newline ) if loop_buf. starts_with ( BRK ) => {
110106 Some ( ( MdTree :: HorizontalRule , parse_to_newline ( loop_buf) . 1 ) )
111107 }
112- ( _, Newline | Whitespace ) if loop_buf. starts_with ( EMP ) => {
113- parse_simple_pat ( loop_buf, EMP , EMP , Po :: None , MdTree :: Emphasis )
108+ ( _, Newline ) if unordered_list_start ( loop_buf) => Some ( parse_unordered_li ( loop_buf) ) ,
109+ _ if let Some ( strong @ ( b"**" | b"__" ) ) = loop_buf. get ( ..2 ) => {
110+ parse_simple_pat ( loop_buf, strong, strong, Po :: None , MdTree :: Strong )
114111 }
115- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( STG ) => {
116- parse_simple_pat ( loop_buf, STG , STG , Po :: None , MdTree :: Strong )
112+ _ if let Some ( emph @ ( b"*" | b"_" ) ) = loop_buf. get ( .. 1 ) => {
113+ parse_simple_pat ( loop_buf, emph , emph , Po :: None , MdTree :: Emphasis )
117114 }
118- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( STK ) => {
115+ _ if loop_buf. starts_with ( STK ) => {
119116 parse_simple_pat ( loop_buf, STK , STK , Po :: None , MdTree :: Strikethrough )
120117 }
121- ( _ , Newline | Whitespace ) if loop_buf. starts_with ( ANC_S ) => {
118+ _ if loop_buf. starts_with ( ANC_S ) => {
122119 let tt_fn = |link| MdTree :: Link { disp : link, link } ;
123120 let ret = parse_simple_pat ( loop_buf, ANC_S , ANC_E , Po :: None , tt_fn) ;
124121 match ret {
@@ -130,11 +127,8 @@ fn parse_recursive<'a>(buf: &'a [u8], ctx: Context) -> MdStream<'_> {
130127 _ => None ,
131128 }
132129 }
133- ( _, Newline ) if ( loop_buf. starts_with ( UL1 ) || loop_buf. starts_with ( UL2 ) ) => {
134- Some ( parse_unordered_li ( loop_buf) )
135- }
136130 ( _, 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 ) => {
131+ _ if loop_buf. starts_with ( LNK_S ) => {
138132 parse_any_link ( loop_buf, top_blk && prev == Prev :: Newline )
139133 }
140134 ( _, Escape | _) => None ,
@@ -251,7 +245,6 @@ fn parse_heading(buf: &[u8]) -> ParseResult<'_> {
251245
252246/// Bulleted list
253247fn parse_unordered_li ( buf : & [ u8 ] ) -> Parsed < ' _ > {
254- debug_assert ! ( buf. starts_with( b"* " ) || buf. starts_with( b"- " ) ) ;
255248 let ( txt, rest) = get_indented_section ( & buf[ 2 ..] ) ;
256249 let ctx = Context { top_block : false , prev : Prev :: Whitespace } ;
257250 let stream = parse_recursive ( trim_ascii_start ( txt) , ctx) ;
@@ -267,25 +260,28 @@ fn parse_ordered_li(buf: &[u8]) -> Parsed<'_> {
267260 ( MdTree :: OrderedListItem ( num, stream) , rest)
268261}
269262
270- /// Find first line that isn't empty or doesn't start with whitespace, that will
271- /// be our contents
272263fn 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 ;
264+ let mut lines = buf. split ( |& byte| byte == b'\n' ) ;
265+ let mut end = lines. next ( ) . map_or ( 0 , |line| line. len ( ) ) ;
266+ for line in lines {
267+ if let Some ( first) = line. first ( ) {
268+ if unordered_list_start ( line) || !first. is_ascii_whitespace ( ) {
269+ break ;
270+ }
283271 }
272+ end += line. len ( ) + 1 ;
284273 }
285274
286275 ( & buf[ ..end] , & buf[ end..] )
287276}
288277
278+ fn unordered_list_start ( mut buf : & [ u8 ] ) -> bool {
279+ while let [ b' ' , rest @ ..] = buf {
280+ buf = rest;
281+ }
282+ matches ! ( buf, [ b'*' | b'-' , b' ' , ..] )
283+ }
284+
289285/// Verify a valid ordered list start (e.g. `1.`) and parse it. Returns the
290286/// parsed number and offset of character after the dot.
291287fn ord_list_start ( buf : & [ u8 ] ) -> Option < ( u16 , usize ) > {
0 commit comments