documentation of $wgShellLocale for details.
=== New features in 1.30 ===
-* …
+* (T37247) Output from Parser::parse() will now be wrapped in a div with
+ class="mw-parser-output" by default. This may be changed or disabled using
+ ParserOptions::setWrapOutputClass().
=== External library changes in 1.30 ===
* …
=== Action API changes in 1.30 ===
-* …
+* (T37247) action=parse output will be wrapped in a div with
+ class="mw-parser-output" by default. This may be changed or disabled using
+ the new 'wrapoutputclass' parameter.
=== Action API internal changes in 1.30 ===
* …
if ( $params['disabletidy'] ) {
$popts->setTidy( false );
}
+ $popts->setWrapOutputClass(
+ $params['wrapoutputclass'] === '' ? false : $params['wrapoutputclass']
+ );
$reset = null;
$suppressCache = false;
'parsetree' => [ 'apihelp-parse-paramvalue-prop-parsetree', CONTENT_MODEL_WIKITEXT ],
],
],
+ 'wrapoutputclass' => 'mw-parser-output',
'pst' => false,
'onlypst' => false,
'effectivelanglinks' => false,
"apihelp-parse-paramvalue-prop-limitreporthtml": "Gives the HTML version of the limit report. Gives no data, when <var>$1disablelimitreport</var> is set.",
"apihelp-parse-paramvalue-prop-parsetree": "The XML parse tree of revision content (requires content model <code>$1</code>)",
"apihelp-parse-paramvalue-prop-parsewarnings": "Gives the warnings that occurred while parsing content.",
+ "apihelp-parse-param-wrapoutputclass": "CSS class to use to wrap the parser output.",
"apihelp-parse-param-pst": "Do a pre-save transform on the input before parsing it. Only valid when used with text.",
"apihelp-parse-param-onlypst": "Do a pre-save transform (PST) on the input, but don't parse it. Returns the same wikitext, after a PST has been applied. Only valid when used with <var>$1text</var>.",
"apihelp-parse-param-effectivelanglinks": "Includes language links supplied by extensions (for use with <kbd>$1prop=langlinks</kbd>).",
"apihelp-parse-paramvalue-prop-limitreporthtml": "{{doc-apihelp-paramvalue|parse|prop|limitreporthtml}}",
"apihelp-parse-paramvalue-prop-parsetree": "{{doc-apihelp-paramvalue|parse|prop|parsetree|params=* $1 - Value of the constant CONTENT_MODEL_WIKITEXT|paramstart=2}}",
"apihelp-parse-paramvalue-prop-parsewarnings": "{{doc-apihelp-paramvalue|parse|prop|parsewarnings}}",
+ "apihelp-parse-param-wrapoutputclass": "{{doc-apihelp-param|parse|wrapoutputclass}}",
"apihelp-parse-param-pst": "{{doc-apihelp-param|parse|pst}}",
"apihelp-parse-param-onlypst": "{{doc-apihelp-param|parse|onlypst}}",
"apihelp-parse-param-effectivelanglinks": "{{doc-apihelp-param|parse|effectivelanglinks}}",
$po = ParserOptions::newFromAnon();
$po->setEditSection( false );
$po->setAllowUnsafeRawHtml( false );
+ $po->setWrapOutputClass( false );
return $po;
}
// from malicious sources. As a precaution, disable
// the <html> parser tag when parsing messages.
$this->mParserOptions->setAllowUnsafeRawHtml( false );
+ // Wrapping messages in an extra <div> is probably not expected. If
+ // they're outside the content area they probably shouldn't be
+ // targeted by CSS that's targeting the parser output, and if
+ // they're inside they already are from the outer div.
+ $this->mParserOptions->setWrapOutputClass( false );
}
return $this->mParserOptions;
$this->mTitle->getPrefixedDBkey() );
}
}
+
+ # Wrap non-interface parser output in a <div> so it can be targeted
+ # with CSS (T37247)
+ $class = $this->mOptions->getWrapOutputClass();
+ if ( $class !== false && !$this->mOptions->getInterfaceMessage() ) {
+ $text = Html::rawElement( 'div', [ 'class' => $class ], $text );
+ }
+
$this->mOutput->setText( $text );
$this->mRevisionId = $oldRevisionId;
*/
private $allowUnsafeRawHtml = true;
+ /**
+ * CSS class to use to wrap output from Parser::parse().
+ * @var string|false
+ */
+ private $wrapOutputClass = 'mw-parser-output';
+
public function getInterwikiMagic() {
return $this->mInterwikiMagic;
}
return $this->allowUnsafeRawHtml;
}
+ /**
+ * Class to use to wrap output from Parser::parse()
+ * @since 1.30
+ * @return string|bool
+ */
+ public function getWrapOutputClass() {
+ return $this->wrapOutputClass;
+ }
+
public function setInterwikiMagic( $x ) {
return wfSetVar( $this->mInterwikiMagic, $x );
}
return wfSetVar( $this->allowUnsafeRawHtml, $x );
}
+ /**
+ * CSS class to use to wrap output from Parser::parse()
+ * @since 1.30
+ * @param string|bool $className Set false to disable wrapping.
+ * @return string|bool Current value
+ */
+ public function setWrapOutputClass( $className ) {
+ if ( $className === true ) { // DWIM, they probably want the default class name
+ $className = 'mw-parser-output';
+ }
+ return wfSetVar( $this->wrapOutputClass, $className );
+ }
+
/**
* Set the redirect target.
*
$user = $context->getUser();
$options = ParserOptions::newFromContext( $context );
+ if ( !isset( $opts['wrap'] ) ) {
+ $options->setWrapOutputClass( false );
+ }
+
if ( isset( $opts['tidy'] ) ) {
if ( !$this->tidySupport->isEnabled() ) {
$this->recorder->skipped( $test, 'tidy extension is not installed' );
# local format section links in edit comment text as local links
# notoc disable table of contents
# thumbsize=NNN set the default thumb size to NNNpx for this test
+# wrap include the normal wrapper <div class="mw-parser-output"> (since 1.30)
#
# You can also set the following parser properties via test options:
# wgEnableUploads, wgAllowExternalImages, wgMaxTocLevel,
// FIXME: This test should pass without setting global content language
$this->options = ParserOptions::newFromUserAndLang( new User, $contLang );
$this->options->setTemplateCallback( [ __CLASS__, 'statelessFetchTemplate' ] );
+ $this->options->setWrapOutputClass( false );
$this->parser = new Parser;
MagicWord::clearCache();
$title = Title::newFromText( 'Unit test' );
$options = ParserOptions::newFromUser( new User() );
+ $options->setWrapOutputClass( false );
$this->assertEquals( "<p>$longLine</p>",
$this->parser->parse( $longLine, $title, $options )->getText() );
}
"WikitextContentTest_testGetParserOutput",
CONTENT_MODEL_WIKITEXT,
"hello ''world''\n",
- "<p>hello <i>world</i>\n</p>"
+ "<div class=\"mw-parser-output\"><p>hello <i>world</i>\n</p>\n\n\n</div>"
],
// TODO: more...?
];
public static function provideGetParserOutput() {
return [
- [ CONTENT_MODEL_WIKITEXT, "hello ''world''\n", "<p>hello <i>world</i></p>" ],
+ [
+ CONTENT_MODEL_WIKITEXT,
+ "hello ''world''\n",
+ "<div class=\"mw-parser-output\"><p>hello <i>world</i></p></div>"
+ ],
// @todo more...?
];
}
$text = $po->getText();
$text = trim( preg_replace( '/<!--.*?-->/sm', '', $text ) ); # strip injected comments
- $text = preg_replace( '!\s*(</p>)!sm', '\1', $text ); # don't let tidy confuse us
+ $text = preg_replace( '!\s*(</p>|</div>)!sm', '\1', $text ); # don't let tidy confuse us
$this->assertEquals( $expectedHtml, $text );
return [ [ "foo<bar" ], [ "foo>bar" ], [ "foo\nbar" ], [ "foo\rbar" ] ];
}
+ private function getParserOptions() {
+ global $wgContLang;
+ $popt = ParserOptions::newFromUserAndLang( new User, $wgContLang );
+ $popt->setWrapOutputClass( false );
+ return $popt;
+ }
+
/**
* @dataProvider provideValidNames
*/
public function testTagHooks( $tag ) {
- global $wgParserConf, $wgContLang;
+ global $wgParserConf;
$parser = new Parser( $wgParserConf );
$parser->setHook( $tag, [ $this, 'tagCallback' ] );
$parserOutput = $parser->parse(
"Foo<$tag>Bar</$tag>Baz",
Title::newFromText( 'Test' ),
- ParserOptions::newFromUserAndLang( new User, $wgContLang )
+ $this->getParserOptions()
);
$this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
* @expectedException MWException
*/
public function testBadTagHooks( $tag ) {
- global $wgParserConf, $wgContLang;
+ global $wgParserConf;
$parser = new Parser( $wgParserConf );
$parser->setHook( $tag, [ $this, 'tagCallback' ] );
$parser->parse(
"Foo<$tag>Bar</$tag>Baz",
Title::newFromText( 'Test' ),
- ParserOptions::newFromUserAndLang( new User, $wgContLang )
+ $this->getParserOptions()
);
$this->fail( 'Exception not thrown.' );
}
* @dataProvider provideValidNames
*/
public function testFunctionTagHooks( $tag ) {
- global $wgParserConf, $wgContLang;
+ global $wgParserConf;
$parser = new Parser( $wgParserConf );
$parser->setFunctionTagHook( $tag, [ $this, 'functionTagCallback' ], 0 );
$parserOutput = $parser->parse(
"Foo<$tag>Bar</$tag>Baz",
Title::newFromText( 'Test' ),
- ParserOptions::newFromUserAndLang( new User, $wgContLang )
+ $this->getParserOptions()
);
$this->assertEquals( "<p>FooOneBaz\n</p>", $parserOutput->getText() );
* @expectedException MWException
*/
public function testBadFunctionTagHooks( $tag ) {
- global $wgParserConf, $wgContLang;
+ global $wgParserConf;
$parser = new Parser( $wgParserConf );
$parser->setFunctionTagHook(
$parser->parse(
"Foo<$tag>Bar</$tag>Baz",
Title::newFromText( 'Test' ),
- ParserOptions::newFromUserAndLang( new User, $wgContLang )
+ $this->getParserOptions()
);
$this->fail( 'Exception not thrown.' );
}