* @var string The contents of <h1> */
private $mPageTitle = '';
+ /**
+ * @var string The displayed title of the page. Different from page title
+ * if overridden by display title magic word or hooks. Can contain safe
+ * HTML. Different from page title which may contain messages such as
+ * "Editing X" which is displayed in h1. This can be used for other places
+ * where the page name is referred on the page.
+ */
+ private $displayTitle;
+
/**
* @var string Contains all of the "<body>" content. Should be private we
* got set/get accessors and the append() method.
return $this->mPageTitle;
}
+ /**
+ * Same as page title but only contains name of the page, not any other text.
+ *
+ * @since 1.32
+ * @param string $html Page title text.
+ * @see OutputPage::setPageTitle
+ */
+ public function setDisplayTitle( $html ) {
+ $this->displayTitle = $html;
+ }
+
+ /**
+ * Returns page display title.
+ *
+ * Performs some normalization, but this not as strict the magic word.
+ *
+ * @since 1.32
+ * @return string HTML
+ */
+ public function getDisplayTitle() {
+ $html = $this->displayTitle;
+ if ( $html === null ) {
+ $html = $this->getTitle()->getPrefixedText();
+ }
+
+ return Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $html ) );
+ }
+
+ /**
+ * Returns page display title without namespace prefix if possible.
+ *
+ * @since 1.32
+ * @return string HTML
+ */
+ public function getUnprefixedDisplayTitle() {
+ $text = $this->getDisplayTitle();
+ $nsPrefix = $this->getTitle()->getNsText() . ':';
+ $prefix = preg_quote( $nsPrefix, '/' );
+
+ return preg_replace( "/^$prefix/i", '', $text );
+ }
+
/**
* Set the Title object to use
*
}
/**
- * Add wikitext with a custom Title object
+ * Add wikitext with a custom Title object.
+ * Output is unwrapped.
*
* @param string $text Wikitext
* @param Title $title
$this->addParserOutput( $parserOutput, [
'enableSectionEditLinks' => false,
+ 'wrapperDivClass' => '',
] );
}
if ( !$this->mArticleBodyOnly ) {
$sk = $this->getSkin();
-
- if ( $sk->shouldPreloadLogo() ) {
- $this->addLogoPreloadLinkHeaders();
- }
}
$linkHeader = $this->getLinkHeader();
foreach ( $this->contentOverrideCallbacks as $callback ) {
$content = $callback( $title );
if ( $content !== null ) {
+ $text = ContentHandler::getContentText( $content );
+ if ( strpos( $text, '</script>' ) !== false ) {
+ // Proactively replace this so that we can display a message
+ // to the user, instead of letting it go to Html::inlineScript(),
+ // where it would be considered a server-side issue.
+ $titleFormatted = $title->getPrefixedText();
+ $content = new JavaScriptContent(
+ Xml::encodeJsCall( 'mw.log.error', [
+ "Cannot preview $titleFormatted due to script-closing tag."
+ ] )
+ );
+ }
return $content;
}
}
] );
}
- /**
- * Add Link headers for preloading the wiki's logo.
- *
- * @since 1.26
- */
- protected function addLogoPreloadLinkHeaders() {
- $logo = ResourceLoaderSkinModule::getLogo( $this->getConfig() );
-
- $tags = [];
- $logosPerDppx = [];
- $logos = [];
-
- if ( !is_array( $logo ) ) {
- // No media queries required if we only have one variant
- $this->addLinkHeader( '<' . $logo . '>;rel=preload;as=image' );
- return;
- }
-
- if ( isset( $logo['svg'] ) ) {
- // No media queries required if we only have a 1x and svg variant
- // because all preload-capable browsers support SVGs
- $this->addLinkHeader( '<' . $logo['svg'] . '>;rel=preload;as=image' );
- return;
- }
-
- foreach ( $logo as $dppx => $src ) {
- // Keys are in this format: "1.5x"
- $dppx = substr( $dppx, 0, -1 );
- $logosPerDppx[$dppx] = $src;
- }
-
- // Because PHP can't have floats as array keys
- uksort( $logosPerDppx, function ( $a , $b ) {
- $a = floatval( $a );
- $b = floatval( $b );
- // Sort from smallest to largest (e.g. 1x, 1.5x, 2x)
- return $a <=> $b;
- } );
-
- foreach ( $logosPerDppx as $dppx => $src ) {
- $logos[] = [ 'dppx' => $dppx, 'src' => $src ];
- }
-
- $logosCount = count( $logos );
- // Logic must match ResourceLoaderSkinModule:
- // - 1x applies to resolution < 1.5dppx
- // - 1.5x applies to resolution >= 1.5dppx && < 2dppx
- // - 2x applies to resolution >= 2dppx
- // Note that min-resolution and max-resolution are both inclusive.
- for ( $i = 0; $i < $logosCount; $i++ ) {
- if ( $i === 0 ) {
- // Smallest dppx
- // min-resolution is ">=" (larger than or equal to)
- // "not min-resolution" is essentially "<"
- $media_query = 'not all and (min-resolution: ' . $logos[ 1 ]['dppx'] . 'dppx)';
- } elseif ( $i !== $logosCount - 1 ) {
- // In between
- // Media query expressions can only apply "not" to the entire expression
- // (e.g. can't express ">= 1.5 and not >= 2).
- // Workaround: Use <= 1.9999 in place of < 2.
- $upper_bound = floatval( $logos[ $i + 1 ]['dppx'] ) - 0.000001;
- $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] .
- 'dppx) and (max-resolution: ' . $upper_bound . 'dppx)';
- } else {
- // Largest dppx
- $media_query = '(min-resolution: ' . $logos[ $i ]['dppx'] . 'dppx)';
- }
-
- $this->addLinkHeader(
- '<' . $logos[$i]['src'] . '>;rel=preload;as=image;media=' . $media_query
- );
- }
- }
-
/**
* Get (and set if not yet set) the CSP nonce.
*