X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fparser%2FBlockLevelPass.php;h=599fbf61de1617c0d1a29a7c6711bd89fb478016;hb=33e4ac5b220b0edbef6774b3d961a3313fbf76e9;hp=cbacd34811f61e59d4cbf707cc90367dba6578b8;hpb=939199bcea28a3b13c49c0f808d11d415660b924;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/parser/BlockLevelPass.php b/includes/parser/BlockLevelPass.php index cbacd34811..599fbf61de 100644 --- a/includes/parser/BlockLevelPass.php +++ b/includes/parser/BlockLevelPass.php @@ -38,6 +38,7 @@ class BlockLevelPass { const COLON_STATE_COMMENT = 5; const COLON_STATE_COMMENTDASH = 6; const COLON_STATE_COMMENTDASHDASH = 7; + const COLON_STATE_LC = 8; /** * Make lists from lines starting with ':', '*', '#', etc. @@ -285,20 +286,20 @@ class BlockLevelPass { # @todo consider using a stack for nestable elements like span, table and div $openMatch = preg_match( '/(?:closeParagraph(); if ( $preOpenMatch && !$preCloseMatch ) { $this->inPre = true; @@ -352,7 +353,7 @@ class BlockLevelPass { } } } - # somewhere above we forget to get out of pre block (bug 785) + # somewhere above we forget to get out of pre block (T2785) if ( $preCloseMatch && $this->inPre ) { $this->inPre = false; } @@ -389,15 +390,14 @@ class BlockLevelPass { * @return string The position of the ':', or false if none found */ private function findColonNoLinks( $str, &$before, &$after ) { - $colonPos = strpos( $str, ':' ); - if ( $colonPos === false ) { + if ( !preg_match( '/:|<|-\{/', $str, $m, PREG_OFFSET_CAPTURE ) ) { # Nothing to find! return false; } - $ltPos = strpos( $str, '<' ); - if ( $ltPos === false || $ltPos > $colonPos ) { + if ( $m[0][0] === ':' ) { # Easy; no tag nesting to worry about + $colonPos = $m[0][1]; $before = substr( $str, 0, $colonPos ); $after = substr( $str, $colonPos + 1 ); return $colonPos; @@ -405,9 +405,10 @@ class BlockLevelPass { # Ugly state machine to walk through avoiding tags. $state = self::COLON_STATE_TEXT; - $level = 0; + $ltLevel = 0; + $lcLevel = 0; $len = strlen( $str ); - for ( $i = 0; $i < $len; $i++ ) { + for ( $i = $m[0][1]; $i < $len; $i++ ) { $c = $str[$i]; switch ( $state ) { @@ -418,7 +419,7 @@ class BlockLevelPass { $state = self::COLON_STATE_TAGSTART; break; case ":": - if ( $level === 0 ) { + if ( $ltLevel === 0 ) { # We found it! $before = substr( $str, 0, $i ); $after = substr( $str, $i + 1 ); @@ -428,35 +429,44 @@ class BlockLevelPass { break; default: # Skip ahead looking for something interesting - $colonPos = strpos( $str, ':', $i ); - if ( $colonPos === false ) { + if ( !preg_match( '/:|<|-\{/', $str, $m, PREG_OFFSET_CAPTURE, $i ) ) { # Nothing else interesting return false; } - $ltPos = strpos( $str, '<', $i ); - if ( $level === 0 ) { - if ( $ltPos === false || $colonPos < $ltPos ) { - # We found it! - $before = substr( $str, 0, $colonPos ); - $after = substr( $str, $colonPos + 1 ); - return $i; - } + if ( $m[0][0] === '-{' ) { + $state = self::COLON_STATE_LC; + $lcLevel++; + $i = $m[0][1] + 1; + } else { + # Skip ahead to next interesting character. + $i = $m[0][1] - 1; } - if ( $ltPos === false ) { - # Nothing else interesting to find; abort! - # We're nested, but there's no close tags left. Abort! - break 2; + break; + } + break; + case self::COLON_STATE_LC: + # In language converter markup -{ ... }- + if ( !preg_match( '/-\{|\}-/', $str, $m, PREG_OFFSET_CAPTURE, $i ) ) { + # Nothing else interesting to find; abort! + # We're nested in language converter markup, but there + # are no close tags left. Abort! + break 2; + } elseif ( $m[0][0] === '-{' ) { + $i = $m[0][1] + 1; + $lcLevel++; + } elseif ( $m[0][0] === '}-' ) { + $i = $m[0][1] + 1; + $lcLevel--; + if ( $lcLevel === 0 ) { + $state = self::COLON_STATE_TEXT; } - # Skip ahead to next tag start - $i = $ltPos; - $state = self::COLON_STATE_TAGSTART; } break; case self::COLON_STATE_TAG: # In a switch ( $c ) { case ">": - $level++; + $ltLevel++; $state = self::COLON_STATE_TEXT; break; case "/": @@ -486,10 +496,12 @@ class BlockLevelPass { case self::COLON_STATE_CLOSETAG: # In a if ( $c === ">" ) { - $level--; - if ( $level < 0 ) { + if ( $ltLevel > 0 ) { + $ltLevel--; + } else { + # ignore the excess close tag, but keep looking for + # colons. (This matches Parsoid behavior.) wfDebug( __METHOD__ . ": Invalid input; too many close tags\n" ); - return false; } $state = self::COLON_STATE_TEXT; } @@ -526,8 +538,11 @@ class BlockLevelPass { throw new MWException( "State machine error in " . __METHOD__ ); } } - if ( $level > 0 ) { - wfDebug( __METHOD__ . ": Invalid input; not enough close tags (level $level, state $state)\n" ); + if ( $ltLevel > 0 || $lcLevel > 0 ) { + wfDebug( + __METHOD__ . ": Invalid input; not enough close tags " . + "(level $ltLevel/$lcLevel, state $state)\n" + ); return false; } return false;