wiki.techinc.nl/tests/phpunit/includes/parser/StripStateTest.php

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

183 lines
5 KiB
PHP
Raw Normal View History

<?php
namespace MediaWiki\Tests\Parser;
use MediaWiki\Parser\Parser;
use MediaWikiIntegrationTestCase;
use StripState;
/**
* @covers \StripState
*/
class StripStateTest extends MediaWikiIntegrationTestCase {
protected function setUp(): void {
parent::setUp();
$this->setContentLang( 'qqx' );
}
private function getMarker() {
static $i;
return Parser::MARKER_PREFIX . '-blah-' . sprintf( '%08X', $i++ ) . Parser::MARKER_SUFFIX;
}
private static function getWarning( $message, $max = '' ) {
return "<span class=\"error\">($message: $max)</span>";
}
public function testAddNoWiki() {
$ss = new StripState;
$marker = $this->getMarker();
$ss->addNoWiki( $marker, '<>' );
$text = "x{$marker}y";
$text = $ss->unstripGeneral( $text );
$text = str_replace( '<', '', $text );
$text = $ss->unstripNoWiki( $text );
$this->assertSame( 'x<>y', $text );
}
public function testAddGeneral() {
$ss = new StripState;
$marker = $this->getMarker();
$ss->addGeneral( $marker, '<>' );
$text = "x{$marker}y";
$text = $ss->unstripNoWiki( $text );
$text = str_replace( '<', '', $text );
$text = $ss->unstripGeneral( $text );
$this->assertSame( 'x<>y', $text );
}
public function testUnstripBoth() {
$ss = new StripState;
$mk1 = $this->getMarker();
$mk2 = $this->getMarker();
$ss->addNoWiki( $mk1, '<1>' );
$ss->addGeneral( $mk2, '<2>' );
$text = "x{$mk1}{$mk2}y";
$text = str_replace( '<', '', $text );
$text = $ss->unstripBoth( $text );
$this->assertSame( 'x<1><2>y', $text );
}
public static function provideUnstripRecursive() {
return [
[ 0, 'text' ],
[ 1, '=text=' ],
[ 2, '==text==' ],
[ 3, '==' . self::getWarning( 'unstrip-depth-warning', 2 ) . '==' ],
];
}
/** @dataProvider provideUnstripRecursive */
public function testUnstripRecursive( $depth, $expected ) {
$ss = new StripState( null, [ 'depthLimit' => 2 ] );
$text = 'text';
for ( $i = 0; $i < $depth; $i++ ) {
$mk = $this->getMarker();
$ss->addNoWiki( $mk, "={$text}=" );
$text = $mk;
}
$text = $ss->unstripNoWiki( $text );
$this->assertSame( $expected, $text );
}
public function testUnstripLoop() {
$ss = new StripState( null, [ 'depthLimit' => 2 ] );
$mk = $this->getMarker();
$ss->addNoWiki( $mk, $mk );
$text = $ss->unstripNoWiki( $mk );
$this->assertSame( self::getWarning( 'parser-unstrip-loop-warning' ), $text );
}
public static function provideUnstripSize() {
return [
[ 0, 'x' ],
[ 1, 'xx' ],
[ 2, str_repeat( self::getWarning( 'unstrip-size-warning', 5 ), 2 ) ]
];
}
/** @dataProvider provideUnstripSize */
public function testUnstripSize( $depth, $expected ) {
$ss = new StripState( null, [ 'sizeLimit' => 5 ] );
$text = 'x';
for ( $i = 0; $i < $depth; $i++ ) {
$mk = $this->getMarker();
$ss->addNoWiki( $mk, $text );
$text = "$mk$mk";
}
$text = $ss->unstripNoWiki( $text );
$this->assertSame( $expected, $text );
}
public static function provideGetLimitReport() {
for ( $i = 1; $i < 4; $i++ ) {
yield [ $i ];
}
}
/** @dataProvider provideGetLimitReport */
public function testGetLimitReport( $depth ) {
$sizeLimit = 100000;
$ss = new StripState( null, [ 'depthLimit' => 5, 'sizeLimit' => $sizeLimit ] );
$text = 'x';
for ( $i = 0; $i < $depth; $i++ ) {
$mk = $this->getMarker();
$ss->addNoWiki( $mk, $text );
$text = "$mk$mk";
}
$text = $ss->unstripNoWiki( $text );
$report = $ss->getLimitReport();
$messages = [];
foreach ( $report as [ $msg, $params ] ) {
$messages[$msg] = $params;
}
$this->assertSame( [ $depth - 1, 5 ], $messages['limitreport-unstrip-depth'] );
$this->assertSame(
[
strlen( $this->getMarker() ) * 2 * ( pow( 2, $depth ) - 2 ) + pow( 2, $depth ),
$sizeLimit
],
$messages['limitreport-unstrip-size' ] );
}
Add support to enable Scribunto & Parsoid to handle nowikis properly * Lua modules have been written to inspect nowiki strip state markers and extract nowiki content to further process them. Callers might have used nowikis in arguments for any number of reasons including needing to have the argument be treated as raw text intead of wikitext. While we might add first-class typing features to wikitext, templates, extensions, and the like in the future which would let Parsoid process template arguments based on type info (rather than as wikitext always), we need a solution now to enable modules to work properly with Parsoid. * The core issue is the decoupled model used by Parsoid where transclusions are preprocessed before further processing. Since nowikis cannot be processed and stripped during preprocessing, Lua modules don't have access to nowiki strip markers in this model. * In this patch, we change extension tag processsing for nowikis. When generating HTML, nowikis are replaced with a 'nowiki' strip marker with the nowiki's "innerXML" (only tag contents). In this patch, during preprocessing, instead of adding a 'general' strip marker with the "outerXML" (tag contents and the tag wrapper), we add a 'nowiki' strip marker with its "outerXML". * Since Parsoid (and any clients using the preprocessed output) will unstrip all strip markers, the shift from a general to nowiki strip marker won't make a difference. * To support Scribunto and Lua modules unstrip usage, this patch adds new functionality to StripState to replace the (preprocessing-)nowiki strip markers with whatever its users want. So, Scribunto could pass in a callback that replaces these with the "innerXML" by stripping out the tag wrapper. * Hat tip to Tim Starling for recommending this strategy. * Updated strip state tests. Bug: T272507 Bug: T299103 Depends-On: Id6ea611549e98893f53094116a3851e9c42b8dc8 Change-Id: Ied0295feab06027a8df885b3215435e596f0353b
2022-08-25 00:25:51 +00:00
public function testReplaceNowikis() {
$ss = new StripState();
// Note that unlike other uses of addNowiki, these add the original source
// with the nowiki wrappers. When wikitext is being processed, the parser
// uses strip markers in this fashion.
$s1 = "[[Foo]]";
$nowikiS1 = "<nowiki>$s1</nowiki>";
$m1 = $this->getMarker();
$ss->addNoWiki( $m1, $nowikiS1 );
$s2 = "[[Foo]]";
$nowikiS2 = "<nowiki>$s2</nowiki>";
$m2 = $this->getMarker();
$ss->addNoWiki( $m2, $nowikiS2 );
$s3 = "";
$nowikiS3 = "<nowiki />";
$m3 = $this->getMarker();
$ss->addNoWiki( $m3, $nowikiS3 );
$text = "$s1; $s2; $s3";
$strippedText = "$m1; $m2; $m3";
$unstrippedText = "$nowikiS1; $nowikiS2; $nowikiS3";
$this->assertSame( $ss->unstripGeneral( $strippedText ), $strippedText );
$this->assertSame( $ss->unstripNoWiki( $strippedText ), $unstrippedText );
$out1 = $ss->replaceNoWikis( $strippedText, static function ( $s ) {
return $s;
} );
$this->assertSame( $out1, $unstrippedText );
// Simulate Scribunto lua modules use of unstripNowiki
$out2 = $ss->replaceNoWikis( $strippedText, static function ( $s ) {
return preg_replace( "#</?nowiki[^>]*>#", '', $s );
} );
$this->assertSame( $out2, $text );
}
}