Merge "Use new ScopedCallback::newScopedIgnoreUserAbort helper function"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sat, 3 Nov 2018 00:43:22 +0000 (00:43 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 3 Nov 2018 00:43:22 +0000 (00:43 +0000)
14 files changed:
RELEASE-NOTES-1.32
RELEASE-NOTES-1.33
includes/OutputPage.php
includes/PHPVersionCheck.php
includes/parser/Parser.php
includes/specials/SpecialMyRedirectPages.php
index.php
maintenance/Maintenance.php
mw-config/index.php
tests/parser/ParserTestRunner.php
tests/parser/TestFileReader.php
tests/parser/parserTests.php
tests/parser/parserTests.txt
tests/phpunit/includes/SampleTest.php

index 2cd1222..438fac3 100644 (file)
@@ -607,6 +607,11 @@ because of Phabricator reports.
   OutputPage::addWikiTextAsContent() instead, which ensures the output is
   tidy and clarifies whether content-language specific postprocessing should
   be done on the text.
+* OutputPage::parse() and OutputPage::parseInline() have been deprecated
+  due to untidy output and inconsistent handling of wrapper divs and
+  interface/content language defaults.  Use OutputPage::parseAsContent(),
+  OutputPage::parseAsInterface(), or OutputPage::parseInlineAsInterface()
+  as appropriate.
 * QuickTemplate::msgHtml() and BaseTemplate::msgHtml() have been deprecated
   as they promote bad practises. I18n messages should always be properly
   escaped.
index b28edec..f6c819d 100644 (file)
@@ -116,11 +116,6 @@ because of Phabricator reports.
   applied for Arabic and Malayalam in the future.  Please enable these on
   your local wiki (if you have them explicitly set to false) and run
   maintenance/cleanupTitles.php to fix any existing page titles.
-* OutputPage::parse() and OutputPage::parseInline() have been deprecated
-  due to untidy output and inconsistent handling of wrapper divs and
-  interface/content language defaults.  Use OutputPage::parseAsContent(),
-  OutputPage::parseAsInterface(), or OutputPage::parseInlineAsInterface()
-  as appropriate.
 * The LegacyHookPreAuthenticationProvider class, deprecated since its creation
   in 1.27 as part of the AuthManager re-write, now emits deprecation warnings.
   This will help identify the issue if you added it to $wgAuthManagerConfig.
index aa2afe9..4a9b542 100644 (file)
@@ -2093,7 +2093,7 @@ class OutputPage extends ContextSource {
         * @param Language|null $language Target language object, will override $interface
         * @throws MWException
         * @return string HTML
-        * @deprecated since 1.33, due to untidy output and inconsistent wrapper;
+        * @deprecated since 1.32, due to untidy output and inconsistent wrapper;
         *  use parseAsContent() if $interface is default value or false, or else
         *  parseAsInterface() if $interface is true.
         */
@@ -2114,7 +2114,7 @@ class OutputPage extends ContextSource {
         * @param bool $linestart Is this the start of a line? (Defaults to true)
         * @throws MWException
         * @return string HTML
-        * @since 1.33
+        * @since 1.32
         */
        public function parseAsContent( $text, $linestart = true ) {
                return $this->parseInternal(
@@ -2135,7 +2135,7 @@ class OutputPage extends ContextSource {
         * @param bool $linestart Is this the start of a line? (Defaults to true)
         * @throws MWException
         * @return string HTML
-        * @since 1.33
+        * @since 1.32
         */
        public function parseAsInterface( $text, $linestart = true ) {
                return $this->parseInternal(
@@ -2158,7 +2158,7 @@ class OutputPage extends ContextSource {
         * @param bool $linestart Is this the start of a line? (Defaults to true)
         * @throws MWException
         * @return string HTML
-        * @since 1.33
+        * @since 1.32
         */
        public function parseInlineAsInterface( $text, $linestart = true ) {
                return Parser::stripOuterParagraph(
@@ -2174,7 +2174,7 @@ class OutputPage extends ContextSource {
         * @param bool $interface Use interface language (instead of content language) while parsing
         *   language sensitive magic words like GRAMMAR and PLURAL
         * @return string HTML
-        * @deprecated since 1.33, due to untidy output and confusing default
+        * @deprecated since 1.32, due to untidy output and confusing default
         *   for $interface.  Use parseInlineAsInterface() if $interface is
         *   the default value or false, or else use
         *   Parser::stripOuterParagraph($outputPage->parseAsContent(...)).
index aee2a0c..8406bfb 100644 (file)
  * Check PHP Version, as well as for composer dependencies in entry points,
  * and display something vaguely comprehensible in the event of a totally
  * unrecoverable error.
+ *
+ * @note Since we can't rely on anything external, the minimum PHP versions
+ * and MW current version are hardcoded in this class.
+ *
+ * @note This class uses setter methods instead of a constructor so that
+ * it can be compatible with PHP 4, PHP 5 and PHP 7 (without warnings).
+ *
  * @class
  */
 class PHPVersionCheck {
@@ -41,29 +48,35 @@ class PHPVersionCheck {
        );
 
        /**
-        * @var string Which entry point we are protecting. One of:
-        *   - index.php
-        *   - load.php
-        *   - api.php
-        *   - mw-config/index.php
-        *   - cli
+        * @var string $format The format used for errors. One of "text" or "html"
+        */
+       var $format = 'text';
+
+       /**
+        * @var string $scriptPath
         */
-       var $entryPoint = null;
+       var $scriptPath = '/';
 
        /**
-        * @param string $entryPoint Which entry point we are protecting. One of:
-        *   - index.php
-        *   - load.php
-        *   - api.php
-        *   - mw-config/index.php
-        *   - cli
+        * Set the format used for errors.
+        *
+        * @param string $format One of "text" or "html"
         */
-       function setEntryPoint( $entryPoint ) {
-               $this->entryPoint = $entryPoint;
+       function setFormat( $format ) {
+               $this->format = $format;
        }
 
        /**
-        * Returns the version of the installed PHP implementation.
+        * Set the script path used for images in HTML-formatted errors.
+        *
+        * @param string $scriptPath
+        */
+       function setScriptPath( $scriptPath ) {
+               $this->scriptPath = $scriptPath;
+       }
+
+       /**
+        * Return the version of the installed PHP implementation.
         *
         * @param string $impl By default, the function returns the info of the currently installed PHP
         *  implementation. Using this parameter the caller can decide, what version info will be
@@ -236,14 +249,8 @@ HTML;
         * @return string
         */
        function getIndexErrorOutput( $title, $longHtml, $shortText ) {
-               $pathinfo = pathinfo( $_SERVER['SCRIPT_NAME'] );
-               if ( $this->entryPoint == 'mw-config/index.php' ) {
-                       $dirname = dirname( $pathinfo['dirname'] );
-               } else {
-                       $dirname = $pathinfo['dirname'];
-               }
                $encLogo =
-                       htmlspecialchars( str_replace( '//', '/', $dirname . '/' ) .
+                       htmlspecialchars( str_replace( '//', '/', $this->scriptPath . '/' ) .
                                'resources/assets/mediawiki.png' );
                $shortHtml = htmlspecialchars( $shortText );
 
@@ -308,23 +315,13 @@ HTML;
         * @param string $longHtml
         */
        function triggerError( $title, $shortText, $longText, $longHtml ) {
-               switch ( $this->entryPoint ) {
-                       case 'cli':
-                               $finalOutput = $longText;
-                               break;
-                       case 'index.php':
-                       case 'mw-config/index.php':
-                               $this->outputHTMLHeader();
-                               $finalOutput = $this->getIndexErrorOutput( $title, $longHtml, $shortText );
-                               break;
-                       case 'load.php':
-                               $this->outputHTMLHeader();
-                               $finalOutput = "/* $shortText */";
-                               break;
-                       default:
-                               $this->outputHTMLHeader();
-                               // Handle everything that's not index.php
-                               $finalOutput = $shortText;
+               if ( $this->format === 'html' ) {
+                       // Used by index.php and mw-config/index.php
+                       $this->outputHTMLHeader();
+                       $finalOutput = $this->getIndexErrorOutput( $title, $longHtml, $shortText );
+               } else {
+                       // Used by Maintenance.php (CLI)
+                       $finalOutput = $longText;
                }
 
                echo "$finalOutput\n";
@@ -336,12 +333,13 @@ HTML;
  * Check PHP version and that external dependencies are installed, and
  * display an informative error if either condition is not satisfied.
  *
- * @note Since we can't rely on anything, the minimum PHP versions and MW current
- * version are hardcoded here.
+ * @param string $format One of "text" or "html"
+ * @param string $scriptPath Used when an error is formatted as HTML.
  */
-function wfEntryPointCheck( $entryPoint ) {
+function wfEntryPointCheck( $format = 'text', $scriptPath = '/' ) {
        $phpVersionCheck = new PHPVersionCheck();
-       $phpVersionCheck->setEntryPoint( $entryPoint );
+       $phpVersionCheck->setFormat( $format );
+       $phpVersionCheck->setScriptPath( $scriptPath );
        $phpVersionCheck->checkRequiredPHPVersion();
        $phpVersionCheck->checkVendorExistence();
        $phpVersionCheck->checkExtensionExistence();
index 721d1fb..3dc2eeb 100644 (file)
@@ -5133,7 +5133,7 @@ class Parser {
                                                                $alt = $this->stripAltText( $match, false );
                                                                break;
                                                        case 'gallery-internal-link':
-                                                               $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
+                                                               $linkValue = $this->stripAltText( $match, false );
                                                                if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
                                                                        // Result of LanguageConverter::markNoConversion
                                                                        // invoked on an external link.
@@ -5329,7 +5329,10 @@ class Parser {
                                                                $value = $this->stripAltText( $value, $holders );
                                                                break;
                                                        case 'link':
-                                                               list( $paramName, $value ) = $this->parseLinkParameter( $value );
+                                                               list( $paramName, $value ) =
+                                                                       $this->parseLinkParameter(
+                                                                               $this->stripAltText( $value, $holders )
+                                                                       );
                                                                if ( $paramName ) {
                                                                        $validated = true;
                                                                        if ( $paramName === 'no-link' ) {
index 4521a53..077fbf1 100644 (file)
@@ -100,7 +100,7 @@ class SpecialMycontributions extends RedirectSpecialPage {
                parent::__construct( 'Mycontributions' );
                $this->mAllowedRedirectParams = [ 'limit', 'namespace', 'tagfilter',
                        'offset', 'dir', 'year', 'month', 'feed', 'deletedOnly',
-                       'nsInvert', 'associated', 'newOnly', 'topOnly' ];
+                       'nsInvert', 'associated', 'newOnly', 'topOnly', 'start', 'end' ];
        }
 
        /**
index 791ffb1..0df4cd0 100644 (file)
--- a/index.php
+++ b/index.php
@@ -34,7 +34,7 @@
 // dependencies. Using dirname( __FILE__ ) here because __DIR__ is PHP5.3+.
 // phpcs:ignore MediaWiki.Usage.DirUsage.FunctionFound
 require_once dirname( __FILE__ ) . '/includes/PHPVersionCheck.php';
-wfEntryPointCheck( 'index.php' );
+wfEntryPointCheck( 'html', dirname( $_SERVER['SCRIPT_NAME'] ) );
 
 require __DIR__ . '/includes/WebStart.php';
 
index c786ce8..e76426d 100644 (file)
@@ -23,7 +23,7 @@
 // Bail on old versions of PHP, or if composer has not been run yet to install
 // dependencies.
 require_once __DIR__ . '/../includes/PHPVersionCheck.php';
-wfEntryPointCheck( 'cli' );
+wfEntryPointCheck( 'text' );
 
 use MediaWiki\Shell\Shell;
 
index a47822b..804d0a1 100644 (file)
@@ -25,7 +25,7 @@
 // dependencies. Using dirname( __FILE__ ) here because __DIR__ is PHP5.3+.
 // phpcs:ignore MediaWiki.Usage.DirUsage.FunctionFound
 require_once dirname( __FILE__ ) . '/../includes/PHPVersionCheck.php';
-wfEntryPointCheck( 'mw-config/index.php' );
+wfEntryPointCheck( 'html', dirname( dirname( $_SERVER['SCRIPT_NAME'] ) ) );
 
 define( 'MW_CONFIG_CALLBACK', 'Installer::overrideConfig' );
 define( 'MEDIAWIKI_INSTALL', true );
index 5c4c48c..12c60a7 100644 (file)
@@ -122,12 +122,6 @@ class ParserTestRunner {
         */
        private $runDisabled;
 
-       /**
-        * Run tests intended only for parsoid
-        * @var bool
-        */
-       private $runParsoid;
-
        /**
         * Disable parse on article insertion
         * @var bool
@@ -170,7 +164,6 @@ class ParserTestRunner {
                $this->fileBackendName = $options['file-backend'] ?? false;
 
                $this->runDisabled = !empty( $options['run-disabled'] );
-               $this->runParsoid = !empty( $options['run-parsoid'] );
 
                $this->disableSaveParse = !empty( $options['disable-save-parse'] );
 
@@ -704,7 +697,6 @@ class ParserTestRunner {
                        foreach ( $filenames as $filename ) {
                                $testFileInfo = TestFileReader::read( $filename, [
                                        'runDisabled' => $this->runDisabled,
-                                       'runParsoid' => $this->runParsoid,
                                        'regex' => $this->regex ] );
 
                                // Don't start the suite if there are no enabled tests in the file
index a96485d..8a11b4c 100644 (file)
@@ -28,7 +28,6 @@ class TestFileReader {
        private $sectionLineNum = [];
        private $lineNum = 0;
        private $runDisabled;
-       private $runParsoid;
        private $regex;
 
        private $articles = [];
@@ -66,11 +65,9 @@ class TestFileReader {
 
                $options = $options + [
                        'runDisabled' => false,
-                       'runParsoid' => false,
                        'regex' => '//',
                ];
                $this->runDisabled = $options['runDisabled'];
-               $this->runParsoid = $options['runParsoid'];
                $this->regex = $options['regex'];
        }
 
@@ -112,13 +109,6 @@ class TestFileReader {
                        }
                }
 
-               if ( preg_match( '/\\bparsoid\\b/i', $data['options'] ) && $nonTidySection === 'html'
-                       && !$this->runParsoid
-               ) {
-                       // A test which normally runs on Parsoid but can optionally be run with MW
-                       return;
-               }
-
                if ( !preg_match( $this->regex, $data['test'] ) ) {
                        // Filtered test
                        return;
index e1d943f..19d5684 100644 (file)
@@ -61,7 +61,6 @@ class ParserTestsMaintenance extends Maintenance {
                        'conjunction with --keep-uploads. Causes a real (non-mock) file backend to ' .
                        'be used.', false, true );
                $this->addOption( 'run-disabled', 'run disabled tests' );
-               $this->addOption( 'run-parsoid', 'run parsoid tests (normally disabled)' );
                $this->addOption( 'disable-save-parse', 'Don\'t run the parser when ' .
                        'inserting articles into the database' );
                $this->addOption( 'dwdiff', 'Use dwdiff to display diff output' );
@@ -181,7 +180,6 @@ class ParserTestsMaintenance extends Maintenance {
                        'regex' => $regex,
                        'keep-uploads' => $this->hasOption( 'keep-uploads' ),
                        'run-disabled' => $this->hasOption( 'run-disabled' ),
-                       'run-parsoid' => $this->hasOption( 'run-parsoid' ),
                        'disable-save-parse' => $this->hasOption( 'disable-save-parse' ),
                        'use-tidy-config' => $this->hasOption( 'use-tidy-config' ),
                        'file-backend' => $this->getOption( 'file-backend' ),
index d836111..30cd372 100644 (file)
@@ -56,6 +56,12 @@ Foo
 FOO
 !!endarticle
 
+!!article
+Foo''s bar''s
+!!text
+Article titles can contain single quotes!
+!!endarticle
+
 !!article
 Template:Foo
 !!text
@@ -2908,6 +2914,23 @@ Self-closed pre
 <pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{}}'></pre>
 !! end
 
+!! test
+Newline before table-close generates empty table row: T208619
+!! wikitext
+{|
+
+|}
+!! html/php+tidy
+<table>
+
+<tbody><tr><td></td></tr></tbody></table>
+!! html/parsoid
+<table data-parsoid='{}'>
+
+</table>
+!! end
+
+# PHP has one more row in the output than Parsoid does: T208619
 !! test
 Parsoid: Don't paragraph-wrap fosterable content even if table syntax is unbalanced
 !! options
@@ -2921,7 +2944,16 @@ parsoid=wt2html
 
 
 |}
-!! html
+!! html/php+tidy
+<table>
+<tbody><tr><td>
+</td><td>
+</td>
+
+
+
+</tr><tr><td></td></tr></tbody></table>
+!! html/parsoid
 <table>
 
 <tbody>
@@ -3199,12 +3231,13 @@ data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},
 
 !! test
 Parsoid: Pipe in template with nested template in external link target in template parameter (seriously)
-!! options
-parsoid
 !! wikitext
 {{echo|[{{fullurl:{{FULLPAGENAME}}|action=edit}} bar]}}
-!! html
-<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[{{fullurl:{{FULLPAGENAME}}|action=edit}} bar]"}},"i":0}}]}'>[Main Page bar]</p>
+!! html/php+tidy
+<p><a rel="nofollow" class="external text" href="http://example.org/index.php?title=Parser_test&amp;action=edit">bar</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" class="external text" href="http://example.org/index.php?title=Parser_test&amp;action=edit" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[{{fullurl:{{FULLPAGENAME}}|action=edit}} bar]"}},"i":0}}]}'>bar</a></p>
 !! end
 
 !! test
@@ -6240,6 +6273,8 @@ parsoid=wt2html
 
 !! end
 
+# Note that the PHP parser output appears to be broken when the table
+# end tag is not separated by a space from the style attribute
 !! test
 A table with stray table end tags on start tag line (wt2html)
 !! options
@@ -6258,7 +6293,22 @@ parsoid=wt2html
 {|style="color: red;" |} id="foo"
 |foo
 |}
-!! html
+!! html/php+tidy
+<table style="&quot;color:">
+
+</table><table style="color: red;">
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+<table style="&quot;color:" id="foo">
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+<table style="color: red;" id="foo">
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+!! html/parsoid
 <table style="color: red;"></table>
 
 <table style="color: red;">
@@ -7489,6 +7539,7 @@ foo
 </tbody></table>
 !!end
 
+# Note: PHP parser omits empty rows
 !! test
 Tables: Digest broken attributes on table and tr tag
 !! options
@@ -7498,7 +7549,12 @@ parsoid=wt2html
 |- || || ++ --
 |- > [
 |}
-!! html
+!! html/php+tidy
+<table>
+
+
+</table>
+!! html/parsoid
 <table>
 <tbody>
 <tr class='mw-empty-elt'></tr>
@@ -7613,7 +7669,7 @@ parsoid=html2wt
 Wikitext tables can be nested inside HTML tables
 !! options
 parsoid=html2wt
-!! html
+!! html/parsoid
 <table data-parsoid='{"stx":"html"}'>
 <tr><td>
 <table>
@@ -7629,6 +7685,15 @@ parsoid=html2wt
 |}
 </td></tr>
 </table>
+!! html/php+tidy
+<table>
+<tbody><tr><td>
+<table>
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+</td></tr>
+</tbody></table>
 !! end
 
 ###
@@ -8022,6 +8087,31 @@ Link containing an equals sign
 <p><a rel="mw:WikiLink" href="./Special:BookSources/isbn=4-00-026157-6" title="Special:BookSources/isbn=4-00-026157-6">Special:BookSources/isbn=4-00-026157-6</a></p>
 !! end
 
+!! article
+Foo & bar
+!! text
+Just a test of an article title containing an ampersand
+!! endarticle
+
+!! test
+Link containing an ampersand
+!! wikitext
+[[Foo & bar]]
+
+[[Foo &amp; bar]]
+
+[[Foo &amp;amp; bar]]
+!! html/php+tidy
+<p><a href="/wiki/Foo_%26_bar" title="Foo &amp; bar">Foo &amp; bar</a>
+</p><p><a href="/wiki/Foo_%26_bar" title="Foo &amp; bar">Foo &amp; bar</a>
+</p><p>[[Foo &amp;amp; bar]]
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Foo_&amp;_bar" title="Foo &amp; bar">Foo &amp; bar</a></p>
+<p><a rel="mw:WikiLink" href="./Foo_&amp;_bar" title="Foo &amp; bar" data-parsoid='{"stx":"simple","a":{"href":"./Foo_&amp;_bar"},"sa":{"href":"Foo &amp;amp; bar"}}'>Foo &amp; bar</a></p>
+<p>[[Foo <span typeof="mw:Entity" data-parsoid='{"src":"&amp;amp;","srcContent":"&amp;"}'>&amp;</span>amp; bar]]</p>
+!! end
+
 !! article
 Foo~bar
 !! text
@@ -8502,27 +8592,32 @@ parsoid=html2wt
 1. Interaction of linktrail and template encapsulation
 !! wikitext
 {{echo|[[Foo]]}}l
+!! html/php+tidy
+<p><a href="/wiki/Foo" title="Foo">Fool</a>
+</p>
 !! html/parsoid
 <p><a rel="mw:WikiLink" href="./Foo" title="Foo" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Foo]]"}},"i":0}},"l"]}'>Fool</a></p>
 !! end
 
 !! test
 2. Interaction of linktrail and template encapsulation
-!! options
-parsoid
 !! wikitext
 {{echo|Some [[Fool]]}}s
-!! html
+!! html/php+tidy
+<p>Some <a href="/index.php?title=Fool&amp;action=edit&amp;redlink=1" class="new" title="Fool (page does not exist)">Fools</a>
+</p>
+!! html/parsoid
 <p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]"}},"i":0}},"s"]}' data-parsoid='{"pi":[[{"k":"1"}]]}'>Some </span><a rel="mw:WikiLink" href="./Fool" title="Fool" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a></p>
 !! end
 
 !! test
 3. Interaction of linktrail and template encapsulation
-!! options
-parsoid
 !! wikitext
 {{echo|Some [[Fool]]s are '''bold and foolish'''}}
-!! html
+!! html/php+tidy
+<p>Some <a href="/index.php?title=Fool&amp;action=edit&amp;redlink=1" class="new" title="Fool (page does not exist)">Fools</a> are <b>bold and foolish</b>
+</p>
+!! html/parsoid
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Some [[Fool]]s are &#39;&#39;&#39;bold and foolish&#39;&#39;&#39;"}},"i":0}}]}' data-parsoid='{"pi":[[{"k":"1"}]]}'>Some <a rel="mw:WikiLink" href="./Fool" title="Fool" data-parsoid='{"stx":"simple","a":{"href":"./Fool"},"sa":{"href":"Fool"},"tail":"s"}'>Fools</a> are <b>bold and foolish</b></p>
 !! end
 
@@ -8702,15 +8797,13 @@ parsoid=wt2html,wt2wt
 !! wikitext
 *[[Wikipedia:ro:Olteni&#0355;a]]
 *[[Wikipedia:ro:Olteni&#355;a]]
-!! html
+!! html/php
 <ul><li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:Olteni&#355;a</a></li>
 <li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:Olteni&#355;a</a></li></ul>
 
 !! html/php+tidy
-<ul>
-<li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:OlteniÅ£a</a></li>
-<li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:OlteniÅ£a</a></li>
-</ul>
+<ul><li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:Olteni&#355;a</a></li>
+<li><a href="http://en.wikipedia.org/wiki/ro:Olteni%C5%A3a" class="extiw" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:Olteni&#355;a</a></li></ul>
 !! html/parsoid
 <ul>
 <li><a rel="mw:WikiLink/Interwiki" href="http://en.wikipedia.org/wiki/ro:OlteniÅ£a" title="wikipedia:ro:OlteniÅ£a">Wikipedia:ro:OlteniÅ£a</a></li>
@@ -9879,12 +9972,14 @@ Nested lists 8 (multiple nesting transitions)
 
 !! end
 
+# XXX this test should be moved to citeParserTests, since it depends
+# on the Cite extension, which is "built in" to Parsoid.
 !! test
 Nested lists 9 (extension interaction)
-!! options
-parsoid
 !! wikitext
 *<references />
+!! html/php+tidy-DISABLED
+<ul><li class="mw-empty-elt"></li></ul>
 !! html/parsoid
 <ul><li data-parsoid='{}'><ol class="mw-references references" typeof="mw:Extension/references" about="#mwt2" data-parsoid='{}' data-mw='{"name":"references","attrs":{}}'></ol></li></ul>
 !! end
@@ -10123,8 +10218,6 @@ parsoid=wt2html,wt2wt
 
 !! test
 Parsoid: Make sure nested lists are serialized on their own line even if HTML contains no newlines
-!! options
-parsoid
 !! wikitext
 #foo
 ##bar
@@ -10134,7 +10227,14 @@ parsoid
 
 :foo
 ::bar
-!! html
+!! html/php+tidy
+<ol><li>foo
+<ol><li>bar</li></ol></li></ol>
+<ul><li>foo
+<ul><li>bar</li></ul></li></ul>
+<dl><dd>foo
+<dl><dd>bar</dd></dl></dd></dl>
+!! html/parsoid
 <ol>
 <li>foo<ol>
 <li>bar</li>
@@ -10913,8 +11013,16 @@ Aoeu
 # From plwiki:PLOS_ONE
 !! test
 Parsoid: Page property magic word with magic word contents
+!! options
+showtitle
+!! config
+wgAllowDisplayTitle=true
+wgRestrictDisplayTitle=false
 !! wikitext
 {{DISPLAYTITLE:''{{PAGENAME}}''}}
+!! html/php+tidy
+<i>Parser test</i>
+
 !! html/parsoid
 <meta property="mw:PageProp/displaytitle" content="Main Page" about="#mwt3" typeof="mw:ExpandedAttrs" data-parsoid='{"src":"{{DISPLAYTITLE:&#39;&#39;{{PAGENAME}}&#39;&#39;}}"}' data-mw='{"attribs":[[{"txt":"content"},{"html":"DISPLAYTITLE:&lt;i data-parsoid=&#39;{\"dsr\":[15,31,2,2]}&#39;>&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=&#39;{\"pi\":[[]],\"dsr\":[17,29,null,null]}&#39; data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAME\",\"function\":\"pagename\"},\"params\":{},\"i\":0}}]}&#39;>Main Page&lt;/span>&lt;/i>"}]]}'/>
 !! end
@@ -12153,7 +12261,18 @@ c}}d
 <table></table>
 
 b}}
-!! html
+!! html/php+tidy
+<p>ab</p><table></table><p>cd
+</p><p>ab
+</p>
+<table></table>
+<p>cd
+</p><p>a
+</p>
+<table></table>
+<p>b
+</p>
+!! html/parsoid
 <p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["a",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b&lt;table>&lt;/table>c"}},"i":0}},"d"]}' data-parsoid='{"pi":[[{"k":"1"}]]}'>ab</p><table about="#mwt1" data-parsoid='{"stx":"html"}'></table><p about="#mwt1">cd</p>
 
 <p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["a",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"b\n&lt;table>&lt;/table>\nc"}},"i":0}},"d"]}' data-parsoid='{"pi":[[{"k":"1"}]]}'>ab</p><span about="#mwt2">
@@ -12169,13 +12288,16 @@ b}}
 
 !! test
 Parsoid: Merge double tds (T52603)
-!! options
-parsoid
 !! wikitext
 {|
 |{{echo|{{!}} foo}}
 |}
-!! html
+!! html/php+tidy
+<table>
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+!! html/parsoid
 <table><tbody>
 <tr><td about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{!}} foo"}},"i":0}}]}'> foo</td></tr>
 </tbody></table>
@@ -12183,15 +12305,20 @@ parsoid
 
 !! test
 Parsoid: Merge double tds in nested transclusion content (T52603)
-!! options
-parsoid
 !! wikitext
 {{echo|<div>}}
 {|
 |{{echo|{{!}} foo}}
 |}
 {{echo|</div>}}
-!! html
+!! html/php+tidy
+<div>
+<table>
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+</div>
+!! html/parsoid
 <div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>"}},"i":0}},"\n{|\n|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"{{!}} foo"}},"i":1}},"\n|}\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"</div>"}},"i":2}}]}'>
 <table><tbody>
 <tr><td data-mw='{"parts":["|"]}'> foo</td></tr>
@@ -12925,14 +13052,15 @@ bar <div>baz</div>
 bar </p><div>baz</div>
 !! end
 
-!!test
+!! test
 Templates: P-wrapping: 1d. Template preceded by comment-only line
-!!options
-parsoid
 !! wikitext
 <!-- foo -->
 {{echo|Bar}}
-!! html
+!! html/php+tidy
+<p>Bar
+</p>
+!! html/parsoid
 <!-- foo -->
 
 <p about="#mwt223" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"Bar"}},"i":0}}]}'>Bar</p>
@@ -12945,7 +13073,10 @@ parsoid=wt2html,wt2wt
 !! wikitext
 {{echo|<div>a</div>}}b{{echo|
 <div>c</div>}}
-!! html
+!! html/php+tidy
+<div>a</div><p>b
+</p><div>c</div>
+!! html/parsoid
 <div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;div>a&lt;/div>"}},"i":0}}]}'>a</div><p>b</p><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"\n&lt;div>c&lt;/div>"}},"i":0}}]}'>
 </span><div about="#mwt2">c</div>
 !! end
@@ -13362,7 +13493,10 @@ parsoid=wt2html,wt2wt
 <table>[[Category:foo1]]<tr><td>foo</td></tr></table>
 <!--Two categories (T52330)-->
 <table>[[Category:bar1]][[Category:bar2]]<tr><td>foo</td></tr></table>
-!! html
+!! html/php+tidy
+<table><tbody><tr><td>foo</td></tr></tbody></table>
+<table><tbody><tr><td>foo</td></tr></tbody></table>
+!! html/parsoid
 <link rel="mw:PageProp/Category" href="./Category:Foo1"><table><tbody><tr><td>foo</td></tr></tbody></table>
 <!--Two categories (T52330)-->
 <link rel="mw:PageProp/Category" href="./Category:Bar1"><link rel="mw:PageProp/Category" href="./Category:Bar2"><table><tbody><tr><td>foo</td></tr></tbody></table>
@@ -13578,7 +13712,9 @@ Templates: Ugly nesting: 3. Quotes opened/closed across templates (echo_with_div
 parsoid=wt2html,wt2wt
 !! wikitext
 {{echo_with_div|''a}}{{echo_with_div|b''c''d}}{{echo_with_div|''e}}
-!! html
+!! html/php+tidy
+<div><i>a</i></div><div><i>b</i>c<i>d</i></div><div>e</div>
+!! html/parsoid
 <div about="#mwt1" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''a&quot;}},&quot;i&quot;:0}}]}"><i>a</i></div>
 <div about="#mwt2" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;b''c''d&quot;}},&quot;i&quot;:0}}]}"><i>b</i>c<i>d</i></div>
 <div about="#mwt3" typeof="mw:Transclusion" data-mw="{&quot;parts&quot;:[{&quot;template&quot;:{&quot;target&quot;:{&quot;wt&quot;:&quot;echo_with_div&quot;,&quot;href&quot;:&quot;./Template:Echo_with_div&quot;},&quot;params&quot;:{&quot;1&quot;:{&quot;wt&quot;:&quot;''e&quot;}},&quot;i&quot;:0}}]}">e</div>
@@ -14286,7 +14422,10 @@ Parsoid: Recognize nowiki with odd capitalization
 parsoid=wt2html
 !! wikitext
 <noWikI ><div>[[foo]]</Nowiki >
-!! html
+!! html/php+tidy
+<p>&lt;div&gt;[[foo]]
+</p>
+!! html/parsoid
 <p><span typeof="mw:Nowiki">&lt;div&gt;[[foo]]</span></p>
 !! end
 
@@ -15001,6 +15140,321 @@ Alt image option should handle most kinds of wikitext without barfing
 <figure class="mw-default-size" typeof="mw:Image/Thumb mw:ExpandedAttrs" about="#mwt2" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"This is the image caption"},{"ck":"alt","ak":"alt=This is a [[link]] and a {{echo|&apos;&apos;bold template&apos;&apos;}}."}]}' data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["alt",{"html":"alt=This is a &lt;a rel=\"mw:WikiLink\" href=\"./Link\" title=\"Link\" data-parsoid=&apos;{\"stx\":\"simple\",\"a\":{\"href\":\"./Link\"},\"sa\":{\"href\":\"link\"},\"dsr\":[65,73,2,2]}&apos;>link&lt;/a> and a &lt;i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid=&apos;{\"dsr\":[80,106,null,null],\"pi\":[[{\"k\":\"1\"}]]}&apos; data-mw=&apos;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&amp;apos;&amp;apos;bold template&amp;apos;&amp;apos;\"}},\"i\":0}}]}&#39;>bold template&lt;/i>."}]]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img alt="This is a link and a bold template." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"This is a link and a bold template.","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=This is a [[link]] and a {{echo|&#39;&#39;bold template&#39;&#39;}}.","resource":"Image:Foobar.jpg"}}'/></a><figcaption>This is the image caption</figcaption></figure>
 !! end
 
+!! test
+Ampersand in alt attribute (T206940)
+!! wikitext
+[[File:Foobar.jpg|alt=&amp;amp;]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|alt=&amp;amp;
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="&amp;amp;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="&amp;amp;" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="&amp;amp;" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="&amp;amp;" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext"></div>
+</li>
+</ul>
+!! end
+
+!! test
+Italics markup in alt attribute (T206940)
+!! wikitext
+[[File:Foobar.jpg|alt=''x''|caption]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|alt=''x''|caption
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="x" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="x" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"alt","ak":"alt=&apos;&apos;x&apos;&apos;"},{"ck":"caption","ak":"caption"}]}' data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img alt="x" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"alt":"x","resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"alt":"alt=&apos;&apos;x&apos;&apos;","resource":"File:Foobar.jpg"}}'/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{"extsrc":"\nFile:Foobar.jpg|alt=&apos;&apos;x&apos;&apos;|caption\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="x" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption</div>
+</li>
+</ul>
+!! end
+
+!! test
+Nowiki markup in alt attribute (T206940)
+!! wikitext
+[[File:Foobar.jpg|alt=<nowiki>''</nowiki>x<nowiki>''</nowiki>|caption]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|alt=<nowiki>''</nowiki>x<nowiki>''</nowiki>|caption
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="&#39;&#39;x&#39;&#39;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="&#39;&#39;x&#39;&#39;" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"alt","ak":"alt=&lt;nowiki>&apos;&apos;&lt;/nowiki>x&lt;nowiki>&apos;&apos;&lt;/nowiki>"},{"ck":"caption","ak":"caption"}],"dsr":[0,71,null,null]}' data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img alt="''x''" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"alt":"&apos;&apos;x&apos;&apos;","resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"alt":"alt=&lt;nowiki>&apos;&apos;&lt;/nowiki>x&lt;nowiki>&apos;&apos;&lt;/nowiki>","resource":"File:Foobar.jpg"}}'/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{"extsrc":"\nFile:Foobar.jpg|alt=&lt;nowiki>&apos;&apos;&lt;/nowiki>x&lt;nowiki>&apos;&apos;&lt;/nowiki>|caption\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="''x''" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption</div>
+</li>
+</ul>
+!! end
+
+!! test
+Nowiki markup in alt attribute (edited html, no data-parsoid) (T206940)
+!! wikitext
+[[File:Foobar.jpg|alt=<nowiki>''x''</nowiki>|caption]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|alt=<nowiki>''x''</nowiki>|caption
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="&#39;&#39;x&#39;&#39;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="&#39;&#39;x&#39;&#39;" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./File:Foobar.jpg"><img alt="''x''" resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><img alt="''x''" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption</div>
+</li>
+</ul>
+!! end
+
+!! test
+Ampersand in link attribute (T206940)
+!! wikitext
+[[File:Foobar.jpg|link=Foo &amp; bar]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=Foo &amp; bar
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/Foo_%26_bar" title="Foo &amp; bar"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Foo_%26_bar"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"link","ak":"link=Foo &amp;amp; bar"}]}'><a href="./Foo_&amp;_bar" data-parsoid='{"a":{"href":"./Foo_&amp;_bar"},"sa":{"href":"link=Foo &amp;amp; bar"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{"extsrc":"\nFile:Foobar.jpg|link=Foo &amp;amp; bar\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foo_&amp;_bar"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext"></div>
+</li>
+</ul>
+!! end
+
+!! test
+Ampersand in link attribute (edited html, no data-parsoid) (T206940)
+!! wikitext
+[[File:Foobar.jpg|link=Foo_&_bar]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=Foo_&_bar
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/Foo_%26_bar" title="Foo &amp; bar"><img alt="Foobar.jpg" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Foo_%26_bar"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image"><a href="./Foo_&amp;_bar"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foo_&amp;_bar"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext"></div>
+</li>
+</ul>
+!! end
+
+!! test
+Italics markup in link attribute (T206940)
+!! wikitext
+[[Foo''s bar''s]]
+
+<!-- Note that "italics" are stripped, even though this is a valid page title -->
+[[File:Foobar.jpg|link=Foo''s bar''s|caption1]]
+
+[[File:Foobar.jpg|link=''Main Page''|caption2]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=Foo''s bar''s|caption1
+File:Foobar.jpg|link=''Main Page''|caption2
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/Foo%27%27s_bar%27%27s" title="Foo&#39;&#39;s bar&#39;&#39;s">Foo''s bar''s</a>
+</p><p><a href="/wiki/Foos_bars" title="caption1"><img alt="caption1" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p><p><a href="/wiki/Main_Page" title="caption2"><img alt="caption2" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Foos_bars"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption1
+</p>
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption2
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Foo''s_bar''s" title="Foo''s bar''s">Foo''s bar''s</a></p>
+
+<!-- Note that "italics" are stripped, even though this is a valid page title -->
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"link","ak":"link=Foo&apos;&apos;s bar&apos;&apos;s"},{"ck":"caption","ak":"caption1"}]}' data-mw='{"caption":"caption1"}'><a href="./Foos_bars" data-parsoid='{"a":{"href":"./Foos_bars"},"sa":{"href":"link=Foo&apos;&apos;s bar&apos;&apos;s"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure-inline></p>
+
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"link","ak":"link=&apos;&apos;Main Page&apos;&apos;"},{"ck":"caption","ak":"caption2"}]}' data-mw='{"caption":"caption2"}'><a href="./Main_Page" data-parsoid='{"a":{"href":"./Main_Page"},"sa":{"href":"link=&apos;&apos;Main Page&apos;&apos;"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{"extsrc":"\nFile:Foobar.jpg|link=Foo&apos;&apos;s bar&apos;&apos;s|caption1\nFile:Foobar.jpg|link=&apos;&apos;Main Page&apos;&apos;|caption2\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foos_bars"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption1</div>
+</li>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption2</div>
+</li>
+</ul>
+!! end
+
+!! test
+Nowiki markup in link attribute (T206940)
+!! wikitext
+[[File:Foobar.jpg|link=Foo<nowiki>''</nowiki>s_bar<nowiki>''</nowiki>s|caption]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=Foo<nowiki>''</nowiki>s_bar<nowiki>''</nowiki>s|caption
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/Foo%27%27s_bar%27%27s" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Foo%27%27s_bar%27%27s"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"link","ak":"link=Foo&lt;nowiki>&apos;&apos;&lt;/nowiki>s_bar&lt;nowiki>&apos;&apos;&lt;/nowiki>s"},{"ck":"caption","ak":"caption"}]}' data-mw='{"caption":"caption"}'><a href="./Foo''s_bar''s" data-parsoid='{"a":{"href":"./Foo&apos;&apos;s_bar&apos;&apos;s"},"sa":{"href":"link=Foo&lt;nowiki>&apos;&apos;&lt;/nowiki>s_bar&lt;nowiki>&apos;&apos;&lt;/nowiki>s"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{"extsrc":"\nFile:Foobar.jpg|link=Foo&lt;nowiki>&apos;&apos;&lt;/nowiki>s_bar&lt;nowiki>&apos;&apos;&lt;/nowiki>s|caption\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foo''s_bar''s"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption</div>
+</li>
+</ul>
+!! end
+
+!! test
+Nowiki markup in link attribute (edited html, no data-parsoid) (T206940)
+!! wikitext
+[[File:Foobar.jpg|link=Foo<nowiki>''s_bar''</nowiki>s|caption]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=Foo<nowiki>''s_bar''</nowiki>s|caption
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/Foo%27%27s_bar%27%27s" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Foo%27%27s_bar%27%27s"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+!! html/parsoid
+<p><figure-inline class="mw-default-size" typeof="mw:Image" data-mw='{"caption":"caption"}'><a href="./Foo''s_bar''s"><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941"/></a></figure-inline></p>
+
+<!-- consistency with gallery extension -->
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foo''s_bar''s"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></figure-inline></div>
+<div class="gallerytext">caption</div>
+</li>
+</ul>
+!! end
+
 !! test
 Image with table with attributes in caption
 !! options
@@ -16377,7 +16831,7 @@ parsoid=wt2html
 * So should this
 
 {{echo|[[Category:Foo]] and this should be part of the same list item}}
-!! html
+!! html/php+tidy
 <ul><li>This and this should be part of the same list item</li>
 <li>So should this and this should be part of the same list item</li></ul>
 !! html/parsoid
@@ -16590,13 +17044,15 @@ Category links with multiple namespaces
 
 !! test
 Parsoid: Serialize link to category page with colon escape
-!! options
-parsoid
 !! wikitext
 
 [[:Category:Foo]]
 [[:Category:Foo|Bar]]
-!! html
+!! html/php+tidy
+<p><a href="/index.php?title=Category:Foo&amp;action=edit&amp;redlink=1" class="new" title="Category:Foo (page does not exist)">Category:Foo</a>
+<a href="/index.php?title=Category:Foo&amp;action=edit&amp;redlink=1" class="new" title="Category:Foo (page does not exist)">Bar</a>
+</p>
+!! html/parsoid
 <p>
 <a rel="mw:WikiLink" href="./Category:Foo" title="Category:Foo">Category:Foo</a>
 <a rel="mw:WikiLink" href="./Category:Foo" title="Category:Foo">Bar</a>
@@ -16643,13 +17099,15 @@ x[[es:Foo]]y
 
 !! test
 Parsoid: Serialize link to file page with colon escape
-!! options
-parsoid
 !! wikitext
 
 [[:File:Foo.png]]
 [[:File:Foo.png|Bar]]
-!! html
+!! html/php+tidy
+<p><a href="/index.php?title=File:Foo.png&amp;action=edit&amp;redlink=1" class="new" title="File:Foo.png (page does not exist)">File:Foo.png</a>
+<a href="/index.php?title=File:Foo.png&amp;action=edit&amp;redlink=1" class="new" title="File:Foo.png (page does not exist)">Bar</a>
+</p>
+!! html/parsoid
 <p>
 <a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">File:Foo.png</a>
 <a rel="mw:WikiLink" href="./File:Foo.png" title="File:Foo.png">Bar</a>
@@ -16658,12 +17116,11 @@ parsoid
 
 !! test
 Parsoid: Serialize a genuine category link without colon escape
-!! options
-parsoid
 !! wikitext
 [[Category:Foo]]
 [[Category:Foo|Bar]]
-!! html
+!! html/php+tidy
+!! html/parsoid
 <link rel="mw:PageProp/Category" href="./Category:Foo">
 <link rel="mw:PageProp/Category" href="./Category:Foo#Bar">
 !! end
@@ -19382,19 +19839,17 @@ parsoid=wt2html,html2html
 !! wikitext
 ==a==
 {| STYLE=__TOC__
-!! html
+!! html/php
 <h2><span class="mw-headline" id="a">a</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 <table style="&#95;_TOC&#95;_">
 <tr><td></td></tr>
 </table>
 
-!! html+tidy
+!! html/php+tidy
 <h2><span class="mw-headline" id="a">a</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: a">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
-<table style="__TOC__">
-<tr>
-<td></td>
-</tr>
-</table>
+<table style="&#95;_TOC&#95;_">
+<tbody><tr><td></td></tr>
+</tbody></table>
 !! html/parsoid
 <h2 id="a">a</h2>
 <table style="__TOC__"></table>
@@ -21752,6 +22207,8 @@ wgRawHtml=1
 !! html/php
 <p><script>alert(1);</script>
 </p>
+!! html/parsoid
+<p><script typeof="mw:Extension/html" about="#mwt3" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"&lt;script>alert(1);&lt;/script>"}}'>alert(1);</script></p>
 !! end
 
 !! test
@@ -24889,9 +25346,30 @@ __TOC__
 
 <h2><span class="mw-headline" id="Style"><style>.foo {}</style>Style<style>.bar {}</style></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Style">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
 
+!! html/parsoid
+<meta property="mw:PageProp/toc" data-parsoid="{}"/>
+<h2 id="Style" data-parsoid="{}"><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo {}"}}'>.foo {}</style>Style<style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".bar {}"}}'>.bar {}</style></h2>
+!! end
+
+!! test
+T198618: script element in ToC
+!! options
+wgRawHtml=1
+!! wikitext
+__TOC__
+==<html><script>alert(1);</script></html>Script<html><script>alert(1);</script></html>==
+!! html/php
+<div id="toc" class="toc"><input type="checkbox" role="button" id="toctogglecheckbox" class="toctogglecheckbox" style="display:none"/><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2><span class="toctogglespan"><label class="toctogglelabel" for="toctogglecheckbox"></label></span></div>
+<ul>
+<li class="toclevel-1 tocsection-1"><a href="#Script"><span class="tocnumber">1</span> <span class="toctext">Script</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="Script"><script>alert(1);</script>Script<script>alert(1);</script></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: Script">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
 !! html/parsoid
 <meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Style" data-parsoid='{}'><style>.foo {}</style>Style<style>.bar {}</style></h2>
+<h2 id="Script" data-parsoid='{}'><script typeof="mw:Extension/html" about="#mwt4" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"&lt;script>alert(1);&lt;/script>"}}'>alert(1);</script>Script<script typeof="mw:Extension/html" about="#mwt6" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"&lt;script>alert(1);&lt;/script>"}}'>alert(1);</script></h2>
 !! end
 
 !! test
@@ -25213,13 +25691,17 @@ Lead
 ###
 !!test
 1. SOL-sensitive wikitext tokens as template-args
-!!options
+!! options
 parsoid=wt2html,wt2wt
 !! wikitext
 {{echo|*a}}
 {{echo|#a}}
 {{echo|:a}}
-!! html
+!! html/php+tidy
+<ul><li>a</li></ul>
+<ol><li>a</li></ol>
+<dl><dd>a</dd></dl>
+!! html/parsoid
 <span about="#mwt1" typeof="mw:Transclusion">
 </span><ul about="#mwt1"><li>a</li>
 </ul>
@@ -27552,17 +28034,20 @@ Indent and comment before table row
 </tbody></table>
 !! end
 
-# Parsoid-specific since PHP parser doesn't handle this mixed tbl-wikitext
+# PHP parser omits empty TR
 !!test
 Empty TR followed by a template-generated TR
-!!options
-parsoid
 !! wikitext
 {|
 |-
 {{echo|<tr><td>foo</td></tr>}}
 |}
-!! html
+!! html/php+tidy
+<table>
+
+<tbody><tr><td>foo</td></tr>
+</tbody></table>
+!! html/parsoid
 <table>
 <tbody>
 <tr class='mw-empty-elt'></tr>
@@ -27571,12 +28056,10 @@ parsoid
 </tbody></table>
 !!end
 
-## PHP and parsoid output differ for this, and since this is primarily
-## for testing Parsoid's serializer, marking this Parsoid only
+## PHP and parsoid output differ for this; as usual PHP omits empty
+## elements, and since it strips the comments the TR is empty.
 !!test
 Empty TR followed by mixed-ws-comment line should RT correctly
-!!options
-parsoid
 !! wikitext
 {|
 |-
@@ -27584,7 +28067,12 @@ parsoid
 |-
 <!--c--> <!--d-->
 |}
-!! html
+!! html/php+tidy
+<table>
+
+
+</table>
+!! html/parsoid
 <table>
 <tbody>
 <tr class='mw-empty-elt'></tr>
@@ -28252,11 +28740,11 @@ parsoid={
 
 !! test
 Image: empty alt attribute (T50924)
-!! options
-parsoid
 !! wikitext
 [[File:Foobar.jpg|thumb|alt=|bar]]
-!! html
+!! html/php+tidy
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>bar</div></div></div>
+!! html/parsoid
 <figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"alt","ak":"alt="},{"ck":"caption","ak":"bar"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img alt="" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"alt":"","resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"alt":"alt=","resource":"File:Foobar.jpg"}}'/></a><figcaption>bar</figcaption></figure>
 !! end
 
@@ -29523,7 +30011,7 @@ parsoid={
 Serialize wikitext list items as HTML list items when embedded in a HTML list
 !! options
 parsoid=html2wt
-!! html
+!! html/parsoid
 <ul data-parsoid='{"stx": "html"}'>
 <li data-parsoid='{}'>a</li>
 <li>b</li>
@@ -29533,17 +30021,22 @@ parsoid=html2wt
 <li>a</li>
 <li>b</li>
 </ul>
+!! html/php+tidy
+<ul>
+<li>a</li>
+<li>b</li>
+</ul>
 !! end
 
-# SSS FIXME: Is this actually a good thing given the
-# odd nested list output that is generated by MW?
+# Nested list should be inside <li>, that is
 # <ul><li>foo<ul>..</ul></li></ul> instead of
 # <ul><li>foo</li><ul>..</ul></ul>
+# See https://stackoverflow.com/questions/5899337/proper-way-to-make-html-nested-list
 !! test
 Wikitext lists can be nested inside HTML lists
 !! options
 parsoid=html2wt
-!! html
+!! html/parsoid
 <ul data-parsoid='{"stx": "html"}'>
 <li data-parsoid='{"stx": "html"}'>a
 <ul><li>b</li></ul>
@@ -29567,6 +30060,17 @@ parsoid=html2wt
 * y
 </li>
 </ul>
+!! html/php+tidy
+<ul>
+<li>a
+<ul><li>b</li></ul>
+</li>
+</ul>
+<ul>
+<li>x
+<ul><li>y</li></ul>
+</li>
+</ul>
 !! end
 
 !! test
@@ -30010,7 +30514,7 @@ parsoid={
   "modes": ["html2wt"],
   "scrubWikitext": true
 }
-!! html
+!! html/parsoid
 <h2><i></i></h2>
 <p><a href='Foo' rel='mw:WikiLink'>foo<i></i>
  </a><b><i></i></b>x</p>
@@ -30028,15 +30532,14 @@ parsoid={
   "modes": ["selser"],
   "scrubWikitext": true,
   "changes": [
-    [ "#x", "after", "<h1><i></i></h1>\n<p> x<b></b></p>"]
+    [ "#x", "after", "<h1><i></i></h1>\n<p> bar<b></b></p>"]
   ]
 }
 !! wikitext
-<span id="x">foo</span>
+<div id="x">foo</div>
 !! wikitext/edited
-<span id="x">foo</span>
-
-x
+<div id="x">foo</div>
+bar
 !! end
 
 !! test
@@ -30169,7 +30672,7 @@ parsoid={
   "modes": ["html2wt"],
   "scrubWikitext": false
 }
-!! html
+!! html/parsoid
 <table>
 <tr><td>a</td></tr>
 <tr><td>-</td></tr>
@@ -30192,7 +30695,7 @@ parsoid={
   "modes": ["html2wt"],
   "scrubWikitext": true
 }
-!! html
+!! html/parsoid
 <table>
 <tr><td>a</td></tr>
 <tr><td>-</td></tr>
@@ -30349,7 +30852,7 @@ parsoid={
   "modes": ["html2wt"],
   "scrubWikitext": true
 }
-!! html
+!! html/parsoid
 <font>foo</font>
 <font><font>bar</font></font>
 <font class="x">boo</font>
@@ -30366,7 +30869,7 @@ parsoid={
   "modes": ["html2wt"],
   "scrubWikitext": false
 }
-!! html
+!! html/parsoid
 <font>foo</font>
 !! wikitext
 <font>foo</font>
@@ -30688,8 +31191,18 @@ styletag=1
 <style>.foo::before { content: "<foo>"; }</style>
 <style data-mw-foobar="baz">.foo::after { content: "<bar>"; }</style>
 </div>
+!! html/parsoid
+<div class="foo">
+<style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style>
+<style data-x-data-mw-foobar="baz" typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{"data-x-data-mw-foobar":"baz"},"body":{"extsrc":".foo::after { content: \"&lt;bar>\"; }"}}'>.foo::after { content: "<bar>"; }</style>
+</div>
 !! end
 
+## Right now, Parsoid doesn't de-duplicate style tags.
+## So, we shouldn't see link tags that need to bypass the sanitizer.
+## In a followup patch, when we de-duplicate style tags and
+## introduce link tags, we'll add a hook for link tags in
+## the parser test runner script.
 !! test
 Validating that <style> isn't wrapped in a paragraph (T186965)
 !! options
@@ -30728,6 +31241,26 @@ bar
 <style>.foo::before { content: "<foo>"; }</style>
 bar
 </p>
+!! html/parsoid
+<p>A style tag, by itself or with other style/link tags, shouldn't be wrapped in a paragraph</p>
+
+<style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style>
+
+<p><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style> &lt;link rel="foo" href="bar"/><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style></p>
+
+<p>But if it's on a line with other content, let it be wrapped.</p>
+
+<p><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style> bar</p>
+
+<p>foo <style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style></p>
+
+<p>foo <style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style> bar</p>
+
+<p>And the same if we have non-paragraph-breaking whitespace</p>
+
+<p>foo
+<style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"&lt;foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style>
+bar</p>
 !! end
 
 !! test
@@ -30770,6 +31303,24 @@ bar
 </p>
 !! end
 
+!! test
+Extension returning multiple nodes starting with a style tag roundtrips
+!! options
+wgRawHtml=1
+!! wikitext
+<table>
+{{echo|<html><style>.hi { color: red; }</style>
+</html>}}
+<tr><td class="hi">ho</td></tr>
+</table>
+!! html/parsoid
+<p about="#mwt5" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE_html","pi":[[{"k":"1"}]]}' data-mw='{"parts":["&lt;table>\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;html>&lt;style>.hi { color: red; }&lt;/style>\n&lt;/html>"}},"i":0}},"\n&lt;tr>&lt;td class=\"hi\">ho&lt;/td>&lt;/tr>\n&lt;/table>"]}'><style typeof="mw:Extension/html" about="#mwt4" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"&lt;style>.hi { color: red; }&lt;/style>\n"}}'>.hi { color: red; }</style><span about="#mwt4">
+</span></p><table about="#mwt5" data-parsoid='{"stx":"html"}'>
+
+<tbody><tr><td class="hi">ho</td></tr>
+</tbody></table>
+!! end
+
 !! test
 Decoding of HTML entities in headings and links for IDs and link fragments (T103714)
 !! config
index 22495d0..da6df70 100644 (file)
@@ -9,7 +9,7 @@ class SampleTest extends MediaWikiLangTestCase {
         * Anything that needs to happen before your tests should go here.
         */
        protected function setUp() {
-               // Be sure to do call the parent setup and teardown functions.
+               // Be sure to call the parent setup and teardown functions.
                // This makes sure that all the various cleanup and restorations
                // happen as they should (including the restoration for setMwGlobals).
                parent::setUp();
@@ -46,7 +46,7 @@ class SampleTest extends MediaWikiLangTestCase {
        }
 
        /**
-        * If you want to run the same test with a variety of data, use a data provider.
+        * If you want to run the same test with a variety of data, use a data provider.
         * see: https://www.phpunit.de/manual/3.4/en/writing-tests-for-phpunit.html
         */
        public static function provideTitles() {