# Render autocomments and make links:
$comment = $this->formatAutoComments( $comment, $title, $local );
- $comment = $this->formatLinksInComment( $comment );
+ $comment = $this->formatLinksInComment( $comment, $title, $local );
wfProfileOut( __METHOD__ );
return $comment;
* @param string $comment Text to format links in
* @return string
*/
- public function formatLinksInComment( $comment ) {
- return preg_replace_callback(
- '/\[\[:?(.*?)(\|(.*?))*\]\]([^[]*)/',
- array( $this, 'formatLinksInCommentCallback' ),
- $comment );
+ public function formatLinksInComment( $comment, $title = null, $local = false ) {
+ $this->commentContextTitle = $title;
+ $this->commentLocal = $local;
+ # Borrowed from Parser::replaceInternalLinks2
+ $parts = StringUtils::explode( '[[', ' ' . $comment );
+ $start = $parts->current();
+ $parts->next();
+ $line = $parts->current();
+ $html = substr( $start, 1 );
+ for ( ; $line !== false && $line !== null ; $parts->next(), $line = $parts->current() ) {
+ $linked = preg_replace_callback(
+ '/^:?(.*?)(\|(.*?))*\]\]([^[]*)/',
+ array( $this, 'formatLinksInCommentCallback' ),
+ $line, -1, $count );
+ if( !$count ) { // No valid link found, put the brackets back
+ $linked = '[[' . $linked;
+ }
+ $html .= $linked;
+ }
+ unset( $this->commentContextTitle );
+ unset( $this->commentLocal );
+ return $html;
}
protected function formatLinksInCommentCallback( $match ) {
$text = $match[1];
}
$submatch = array();
+ $thelink = null;
if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
# Media link; trail not supported.
- $linkRegexp = '/\[\[(.*?)\]\]/';
+ $linkRegexp = '/^(.*?)\]\]/';
$title = Title::makeTitleSafe( NS_FILE, $submatch[1] );
$thelink = $this->makeMediaLinkObj( $title, $text );
} else {
} else {
$trail = "";
}
- $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
+ $linkRegexp = '/^(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
if (isset($match[1][0]) && $match[1][0] == ':')
$match[1] = substr($match[1], 1);
list( $inside, $trail ) = Linker::splitTrail( $trail );
- $thelink = $this->link(
- Title::newFromText( $match[1] ),
- $text . $inside
- ) . $trail;
+
+ $linkText = $text;
+ $linkTarget = Linker::normalizeSubpageLink( $this->commentContextTitle,
+ $match[1], $linkText );
+
+ $target = Title::newFromText( $linkTarget );
+ if( $target ) {
+ if( $target->getText() == '' && !$this->commentLocal && $this->commentContextTitle ) {
+ $newTarget = clone( $this->commentContextTitle );
+ $newTarget->setFragment( '#' . $target->getFragment() );
+ $target = $newTarget;
+ }
+ $thelink = $this->link(
+ $target,
+ $linkText . $inside
+ ) . $trail;
+ }
+ }
+ if( $thelink ) {
+ // If the link is still valid, go ahead and replace it in!
+ $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
}
- $comment = preg_replace( $linkRegexp, StringUtils::escapeRegexReplacement( $thelink ), $comment, 1 );
return $comment;
}
+
+ static function normalizeSubpageLink( $contextTitle, $target, &$text ) {
+ # Valid link forms:
+ # Foobar -- normal
+ # :Foobar -- override special treatment of prefix (images, language links)
+ # /Foobar -- convert to CurrentPage/Foobar
+ # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial / from text
+ # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage
+ # ../Foobar -- convert to CurrentPage/Foobar, from CurrentPage/CurrentSubPage
+
+ wfProfileIn( __METHOD__ );
+ $ret = $target; # default return value is no change
+
+ # Some namespaces don't allow subpages,
+ # so only perform processing if subpages are allowed
+ if( $contextTitle && MWNamespace::hasSubpages( $contextTitle->getNamespace() ) ) {
+ $hash = strpos( $target, '#' );
+ if( $hash !== false ) {
+ $suffix = substr( $target, $hash );
+ $target = substr( $target, 0, $hash );
+ } else {
+ $suffix = '';
+ }
+ # bug 7425
+ $target = trim( $target );
+ # Look at the first character
+ if( $target != '' && $target{0} === '/' ) {
+ # / at end means we don't want the slash to be shown
+ $m = array();
+ $trailingSlashes = preg_match_all( '%(/+)$%', $target, $m );
+ if( $trailingSlashes ) {
+ $noslash = $target = substr( $target, 1, -strlen($m[0][0]) );
+ } else {
+ $noslash = substr( $target, 1 );
+ }
+
+ $ret = $contextTitle->getPrefixedText(). '/' . trim($noslash) . $suffix;
+ if( '' === $text ) {
+ $text = $target . $suffix;
+ } # this might be changed for ugliness reasons
+ } else {
+ # check for .. subpage backlinks
+ $dotdotcount = 0;
+ $nodotdot = $target;
+ while( strncmp( $nodotdot, "../", 3 ) == 0 ) {
+ ++$dotdotcount;
+ $nodotdot = substr( $nodotdot, 3 );
+ }
+ if($dotdotcount > 0) {
+ $exploded = explode( '/', $contextTitle->GetPrefixedText() );
+ if( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page
+ $ret = implode( '/', array_slice( $exploded, 0, -$dotdotcount ) );
+ # / at the end means don't show full path
+ if( substr( $nodotdot, -1, 1 ) === '/' ) {
+ $nodotdot = substr( $nodotdot, 0, -1 );
+ if( '' === $text ) {
+ $text = $nodotdot . $suffix;
+ }
+ }
+ $nodotdot = trim( $nodotdot );
+ if( $nodotdot != '' ) {
+ $ret .= '/' . $nodotdot;
+ }
+ $ret .= $suffix;
+ }
+ }
+ }
+ }
+
+ wfProfileOut( __METHOD__ );
+ return $ret;
+ }
/**
* Wrap a comment in standard punctuation and formatting if
/** @todo document */
function tocList($toc) {
- global $wgJsMimeType;
$title = wfMsgHtml('toc') ;
return
- '<table id="toc" class="toc" summary="' . $title .'"><tr><td>'
+ '<table id="toc" class="toc"><tr><td>'
. '<div id="toctitle"><h2>' . $title . "</h2></div>\n"
. $toc
# no trailing newline, script should not be wrapped in a
# paragraph
. "</ul>\n</td></tr></table>"
- . '<script type="' . $wgJsMimeType . '">'
- . ' if (window.showTocToggle) {'
- . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
- . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
- . ' showTocToggle();'
- . ' } '
- . "</script>\n";
+ . Html::inlineScript(
+ 'if (window.showTocToggle) {'
+ . ' var tocShowText = "' . Xml::escapeJsString( wfMsg('showtoc') ) . '";'
+ . ' var tocHideText = "' . Xml::escapeJsString( wfMsg('hidetoc') ) . '";'
+ . ' showTocToggle();'
+ . ' } ' )
+ . "\n";
}
/**
foreach ( $tree as $section ) {
if ( $section['toclevel'] > $lastLevel )
$toc .= $this->tocIndent();
- else if ( $secton['toclevel'] < $lastLevel )
+ else if ( $section['toclevel'] < $lastLevel )
$toc .= $this->tocUnindent(
$lastLevel - $section['toclevel'] );
else
* @return string HTML headline
*/
public function makeHeadline( $level, $attribs, $anchor, $text, $link, $legacyAnchor = false ) {
- $ret = "<h$level id=\"$anchor\"$attribs"
+ $ret = "<h$level$attribs"
. $link
- . " <span class=\"mw-headline\">$text</span>"
+ . " <span class=\"mw-headline\" id=\"$anchor\">$text</span>"
. "</h$level>";
if ( $legacyAnchor !== false ) {
$ret = "<a id=\"$legacyAnchor\"></a>$ret";