@@ -191,7 +191,7 @@ class MarkdownParser extends Parser
191191 // or
192192 '| ' .
193193 // Non-space, non-control characters.
194- '[^\s\p{Cc}]+ ' .
194+ '[^\s\p{Cc}]+? ' .
195195 ') ' .
196196 ') ' ;
197197
@@ -397,7 +397,7 @@ class MarkdownParser extends Parser
397397 'interrupts_p ' => true ,
398398 'marker_pattern ' => '/^((?P<bullet>[*+-])|(?P<number>\d+)(?P<num_punct>[.)]))\h+/u ' ,
399399 'opener_test ' => 'testOpensListItem ' ,
400- 'continue_test ' => ' testContinuesListItem ' ,
400+ 'continue_test ' => false ,
401401 'closer_test ' => 'testClosesListItem ' ,
402402 'add ' => 'addListItem ' ,
403403 'append ' => null ,
@@ -1226,12 +1226,16 @@ protected function testIsIndentedCode(array $line_info): bool
12261226 return true ;
12271227 }
12281228
1229+ if ($ this ->in_code === 2 ) {
1230+ return false ;
1231+ }
1232+
12291233 if ($ this ->testIsBlank ($ line_info ) && $ this ->in_code === 1 ) {
12301234 return true ;
12311235 }
12321236
12331237 if ($ line_info ['indent ' ] < 4 ) {
1234- $ this ->in_code = $ this -> in_code === 1 ? 0 : $ this -> in_code ;
1238+ $ this ->in_code = 0 ;
12351239
12361240 return false ;
12371241 }
@@ -1248,7 +1252,7 @@ protected function testIsIndentedCode(array $line_info): bool
12481252 && $ open_block ['properties ' ]['indent ' ] >= $ line_info ['indent ' ]
12491253 )
12501254 ) {
1251- $ this ->in_code = $ this -> in_code === 1 ? 0 : $ this -> in_code ;
1255+ $ this ->in_code = 0 ;
12521256
12531257 return false ;
12541258 }
@@ -1395,21 +1399,6 @@ protected function testOpensListItem(array $line_info): bool
13951399 );
13961400 }
13971401
1398- /**
1399- * Tests whether a line is part of a list item.
1400- *
1401- * @param array $line_info Info about the current line.
1402- * @return bool Whether this line is part of a list item.
1403- */
1404- protected function testContinuesListItem (array $ line_info , int $ last_container , int $ o ): bool
1405- {
1406- return (bool ) (
1407- $ this ->open [$ o ]['type ' ] === 'list_item '
1408- && $ this ->open [$ o - 1 ]['type ' ] === 'list '
1409- && $ line_info ['indent ' ] >= $ this ->open [$ o ]['properties ' ]['indent ' ]
1410- );
1411- }
1412-
14131402 /**
14141403 * Tests whether a line closes a list item.
14151404 *
@@ -1827,6 +1816,21 @@ protected function addListItem(array $line_info, int $last_container, int $o): v
18271816
18281817 $ indent = $ line_info ['indent ' ] + mb_strlen ($ marker ) + strspn ($ line_info ['content ' ], ' ' , strlen ($ marker ));
18291818
1819+ // Check for nested lists.
1820+ if (
1821+ $ this ->open [$ last_container ]['type ' ] === 'list '
1822+ && $ line_info ['indent ' ] >= $ this ->open [$ last_container ]['properties ' ]['indent ' ]
1823+ ) {
1824+ // Close the open paragraph (or whatever) inside the open list item.
1825+ while ($ this ->open [$ o ]['type ' ] !== 'list_item ' ) {
1826+ $ this ->getMethod ($ this ->block_types [$ this ->open [$ o ]['type ' ]]['close ' ] ?? 'closeBlock ' )($ o );
1827+ $ o --;
1828+ }
1829+
1830+ // Consider the open list item to be our container.
1831+ $ last_container = $ o ;
1832+ }
1833+
18301834 // If this list item doesn't match the existing list's type,
18311835 // exit the existing list so we can start a new one.
18321836 if (
@@ -2475,8 +2479,41 @@ protected function parseInlineSecondPass(array $content): array
24752479 }
24762480
24772481 // We need more info to make decisions about this run of delimiter chars.
2478- $ prev_char = html_entity_decode ($ chars [$ start - 1 ] ?? ' ' );
2479- $ next_char = html_entity_decode ($ chars [$ i + 1 ] ?? ' ' );
2482+ if (isset ($ chars [$ start - 1 ])) {
2483+ $ prev_char = $ chars [$ start - 1 ];
2484+ } elseif (!isset ($ content [$ c - 1 ])) {
2485+ $ prev_char = ' ' ;
2486+ } else {
2487+ $ temp = $ content [$ c - 1 ];
2488+
2489+ while (isset ($ temp [array_key_last ($ temp )]['content ' ])) {
2490+ $ temp = $ temp [array_key_last ($ temp )]['content ' ];
2491+ }
2492+
2493+ if (is_string (end ($ temp ['content ' ]))) {
2494+ $ prev_char = mb_substr (end ($ temp ['content ' ]), -1 );
2495+ } else {
2496+ $ prev_char = ' ' ;
2497+ }
2498+ }
2499+
2500+ if (isset ($ chars [$ i + 1 ])) {
2501+ $ next_char = $ chars [$ i + 1 ];
2502+ } elseif (!isset ($ content [$ c + 1 ])) {
2503+ $ next_char = ' ' ;
2504+ } else {
2505+ $ temp = $ content [$ c + 1 ];
2506+
2507+ while (isset ($ temp [0 ]['content ' ])) {
2508+ $ temp = $ temp [0 ]['content ' ];
2509+ }
2510+
2511+ if (is_string (reset ($ temp ['content ' ]))) {
2512+ $ next_char = mb_substr (reset ($ temp ['content ' ]), 0 , 1 );
2513+ } else {
2514+ $ next_char = ' ' ;
2515+ }
2516+ }
24802517
24812518 $ prev_is_space = preg_match ('/\s/u ' , $ prev_char );
24822519 $ prev_is_punct = $ prev_is_space ? false : preg_match ('/\pP/u ' , $ prev_char );
@@ -2660,10 +2697,8 @@ protected function parseLink(array $chars, int &$i, array &$content): void
26602697
26612698 $ str = implode ('' , array_slice ($ chars , $ delim ['properties ' ]['position ' ], $ i - $ delim ['properties ' ]['position ' ])) . '] ' . mb_substr (implode ('' , $ chars ), $ i + 1 );
26622699
2663- $ prefix = $ delim ['type ' ] === '![ ' ? '! ' : '' ;
2664-
26652700 // Inline link/image?
2666- if (preg_match ('~^ ' . $ prefix . self ::REGEX_LINK_INLINE . '~u ' , $ str , $ matches )) {
2701+ if (preg_match ('~^ ' . self ::REGEX_LINK_INLINE . '~u ' , $ str , $ matches )) {
26672702 $ this ->parseEmphasis ($ content , $ c );
26682703
26692704 $ text = array_slice ($ content , $ c + 1 );
@@ -2693,7 +2728,7 @@ protected function parseLink(array $chars, int &$i, array &$content): void
26932728 self ::REGEX_LINK_REF_COLLAPSED ,
26942729 self ::REGEX_LINK_REF_SHORTCUT ,
26952730 ] as $ regex ) {
2696- if (preg_match ('~ ' . $ prefix . $ regex . '~u ' , $ str , $ matches )) {
2731+ if (preg_match ('~ ' . $ regex . '~u ' , $ str , $ matches )) {
26972732 break ;
26982733 }
26992734 }
@@ -3256,6 +3291,8 @@ protected function renderBlockquote(array $element): void
32563291 */
32573292 protected function renderList (array $ element ): void
32583293 {
3294+ static $ nesting_level = 0 ;
3295+
32593296 switch ($ this ->output_type ) {
32603297 case self ::OUTPUT_BBC :
32613298 if ($ element ['content ' ] === []) {
@@ -3270,7 +3307,10 @@ protected function renderList(array $element): void
32703307 return ;
32713308 }
32723309
3273- $ style_type = $ element ['properties ' ]['ordered ' ] ? 'decimal ' : 'disc ' ;
3310+ $ ordered_styles = ['decimal ' , 'lower-roman ' , 'lower-alpha ' ];
3311+ $ unordered_styles = ['disc ' , 'circle ' , 'square ' ];
3312+
3313+ $ style_type = $ element ['properties ' ]['ordered ' ] ? $ ordered_styles [$ nesting_level % 3 ] : $ unordered_styles [$ nesting_level % 3 ];
32743314
32753315 foreach (BBCodeParser::getCodes () as $ code ) {
32763316 if (
@@ -3297,7 +3337,9 @@ protected function renderList(array $element): void
32973337 $ this ->rendered .= "\n" ;
32983338
32993339 foreach ($ element ['content ' ] as $ content_element ) {
3340+ $ nesting_level ++;
33003341 $ this ->render ($ content_element );
3342+ $ nesting_level --;
33013343 }
33023344
33033345 switch ($ this ->output_type ) {
0 commit comments