*/
use MediaWiki\Linker\LinkRenderer;
use MediaWiki\MediaWikiServices;
+use MediaWiki\Special\SpecialPageFactory;
use Wikimedia\ScopedCallback;
/**
* - Parser::getPreloadText()
* removes <noinclude> sections and <includeonly> tags
*
- * Globals used:
- * object: $wgContLang
- *
* @warning $wgUser or $wgTitle or $wgRequest or $wgLang. Keep them away!
*
* @par Settings:
const TOC_START = '<mw:toc>';
const TOC_END = '</mw:toc>';
+ /** @var int Assume that no output will later be saved this many seconds after parsing */
+ const MAX_TTS = 900;
+
# Persistent:
public $mTagHooks = [];
public $mTransparentTagHooks = [];
public $mImageParams = [];
public $mImageParamsMagicArray = [];
public $mMarkerIndex = 0;
+ /**
+ * @var bool Whether firstCallInit still needs to be called
+ */
public $mFirstCall = true;
# Initialised by initialiseVariables()
*/
protected $mLinkRenderer;
+ /** @var MagicWordFactory */
+ private $magicWordFactory;
+
+ /** @var Language */
+ private $contLang;
+
+ /** @var ParserFactory */
+ private $factory;
+
+ /** @var SpecialPageFactory */
+ private $specialPageFactory;
+
+ /** @var Config */
+ private $siteConfig;
+
/**
- * @param array $conf
+ * @param array $parserConf See $wgParserConf documentation
+ * @param MagicWordFactory|null $magicWordFactory
+ * @param Language|null $contLang Content language
+ * @param ParserFactory|null $factory
+ * @param string|null $urlProtocols As returned from wfUrlProtocols()
+ * @param SpecialPageFactory|null $spFactory
+ * @param Config|null $siteConfig
*/
- public function __construct( $conf = [] ) {
- $this->mConf = $conf;
- $this->mUrlProtocols = wfUrlProtocols();
+ public function __construct(
+ array $parserConf = [], MagicWordFactory $magicWordFactory = null,
+ Language $contLang = null, ParserFactory $factory = null, $urlProtocols = null,
+ SpecialPageFactory $spFactory = null, Config $siteConfig = null
+ ) {
+ $this->mConf = $parserConf;
+ $this->mUrlProtocols = $urlProtocols ?? wfUrlProtocols();
$this->mExtLinkBracketedRegex = '/\[(((?i)' . $this->mUrlProtocols . ')' .
self::EXT_LINK_ADDR .
self::EXT_LINK_URL_CLASS . '*)\p{Zs}*([^\]\\x00-\\x08\\x0a-\\x1F\\x{FFFD}]*?)\]/Su';
- if ( isset( $conf['preprocessorClass'] ) ) {
- $this->mPreprocessorClass = $conf['preprocessorClass'];
- } elseif ( defined( 'HPHP_VERSION' ) ) {
- # Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop
+ if ( isset( $parserConf['preprocessorClass'] ) ) {
+ $this->mPreprocessorClass = $parserConf['preprocessorClass'];
+ } elseif ( wfIsHHVM() ) {
+ # Under HHVM Preprocessor_Hash is much faster than Preprocessor_DOM
$this->mPreprocessorClass = Preprocessor_Hash::class;
} elseif ( extension_loaded( 'domxml' ) ) {
# PECL extension that conflicts with the core DOM extension (T15770)
$this->mPreprocessorClass = Preprocessor_Hash::class;
}
wfDebug( __CLASS__ . ": using preprocessor: {$this->mPreprocessorClass}\n" );
+
+ $services = MediaWikiServices::getInstance();
+ $this->magicWordFactory = $magicWordFactory ??
+ $services->getMagicWordFactory();
+
+ $this->contLang = $contLang ?? $services->getContentLanguage();
+
+ $this->factory = $factory ?? $services->getParserFactory();
+ $this->specialPageFactory = $spFactory ?? $services->getSpecialPageFactory();
+ $this->siteConfig = $siteConfig ?? MediaWikiServices::getInstance()->getMainConfig();
}
/**
* @private
*/
public function clearState() {
- if ( $this->mFirstCall ) {
- $this->firstCallInit();
- }
+ $this->firstCallInit();
$this->mOutput = new ParserOutput;
$this->mOptions->registerWatcher( [ $this->mOutput, 'recordOption' ] );
$this->mAutonumber = 0;
* Do not call this function recursively.
*
* @param string $text Text we want to parse
+ * @param-taint $text escapes_htmlnoent
* @param Title $title
* @param ParserOptions $options
* @param bool $linestart
* @param bool $clearState
- * @param int $revid Number to pass in {{REVISIONID}}
+ * @param int|null $revid Number to pass in {{REVISIONID}}
* @return ParserOutput A ParserOutput
+ * @return-taint escaped
*/
public function parse(
$text, Title $title, ParserOptions $options,
|| isset( $this->mDoubleUnderscores['notitleconvert'] )
|| $this->mOutput->getDisplayTitle() !== false )
) {
- $convruletitle = $this->getConverterLanguage()->getConvRuleTitle();
+ $convruletitle = $this->getTargetLanguage()->getConvRuleTitle();
if ( $convruletitle ) {
$this->mOutput->setTitleText( $convruletitle );
} else {
- $titleText = $this->getConverterLanguage()->convertTitle( $title );
+ $titleText = $this->getTargetLanguage()->convertTitle( $title );
$this->mOutput->setTitleText( $titleText );
}
}
# with CSS (T37247)
$class = $this->mOptions->getWrapOutputClass();
if ( $class !== false && !$this->mOptions->getInterfaceMessage() ) {
- $text = Html::rawElement( 'div', [ 'class' => $class ], $text );
+ $this->mOutput->addWrapperDivClass( $class );
}
$this->mOutput->setText( $text );
* @return string
*/
protected function makeLimitReport() {
- global $wgShowHostnames;
-
$maxIncludeSize = $this->mOptions->getMaxIncludeSize();
$cpuTime = $this->mOutput->getTimeSinceStart( 'cpu' );
Hooks::run( 'ParserLimitReportPrepare', [ $this, $this->mOutput ] );
$limitReport = "NewPP limit report\n";
- if ( $wgShowHostnames ) {
+ if ( $this->siteConfig->get( 'ShowHostnames' ) ) {
$limitReport .= 'Parsed by ' . wfHostname() . "\n";
}
$limitReport .= 'Cached time: ' . $this->mOutput->getCacheTime() . "\n";
// Since we're not really outputting HTML, decode the entities and
// then re-encode the things that need hiding inside HTML comments.
$limitReport = htmlspecialchars_decode( $limitReport );
- // Run deprecated hook
- Hooks::run( 'ParserLimitReport', [ $this, &$limitReport ], '1.22' );
// Sanitize for comment. Note '‐' in the replacement is U+2010,
// which looks much like the problematic '-'.
// Add on template profiling data in human/machine readable way
$dataByFunc = $this->mProfiler->getFunctionStats();
uasort( $dataByFunc, function ( $a, $b ) {
- return $a['real'] < $b['real']; // descending order
+ return $b['real'] <=> $a['real']; // descending order
} );
$profileReport = [];
foreach ( array_slice( $dataByFunc, 0, 10 ) as $item ) {
$this->mOutput->setLimitReportData( 'limitreport-timingprofile', $profileReport );
// Add other cache related metadata
- if ( $wgShowHostnames ) {
+ if ( $this->siteConfig->get( 'ShowHostnames' ) ) {
$this->mOutput->setLimitReportData( 'cachereport-origin', wfHostname() );
}
$this->mOutput->setLimitReportData( 'cachereport-timestamp',
* $text are not expanded
*
* @param string $text Text extension wants to have parsed
+ * @param-taint $text escapes_htmlnoent
* @param bool|PPFrame $frame The frame to use for expanding any template variables
* @return string UNSAFE half-parsed HTML
+ * @return-taint escaped
*/
public function recursiveTagParse( $text, $frame = false ) {
// Avoid PHP 7.1 warning from passing $this by reference
* @since 1.25
*
* @param string $text Text extension wants to have parsed
+ * @param-taint $text escapes_htmlnoent
* @param bool|PPFrame $frame The frame to use for expanding any template variables
* @return string Fully parsed HTML
+ * @return-taint escaped
*/
public function recursiveTagParseFully( $text, $frame = false ) {
$text = $this->recursiveTagParse( $text, $frame );
* Also removes comments.
* Do not call this function recursively.
* @param string $text
- * @param Title $title
+ * @param Title|null $title
* @param ParserOptions $options
* @param int|null $revid
* @param bool|PPFrame $frame
/**
* Accessor/mutator for the Title object
*
- * @param Title $x Title object or null to just get the current one
+ * @param Title|null $x Title object or null to just get the current one
* @return Title
*/
public function Title( $x = null ) {
/**
* Accessor/mutator for the ParserOptions object
*
- * @param ParserOptions $x New value or null to just get the current one
+ * @param ParserOptions|null $x New value or null to just get the current one
* @return ParserOptions Current ParserOptions object
*/
public function Options( $x = null ) {
/**
* Get the language object for language conversion
+ * @deprecated since 1.32, just use getTargetLanguage()
* @return Language|null
*/
public function getConverterLanguage() {
return $this->mLinkRenderer;
}
+ /**
+ * Get the MagicWordFactory that this Parser is using
+ *
+ * @since 1.32
+ * @return MagicWordFactory
+ */
+ public function getMagicWordFactory() {
+ return $this->magicWordFactory;
+ }
+
+ /**
+ * Get the content language that this Parser is using
+ *
+ * @since 1.32
+ * @return Language
+ */
+ public function getContentLanguage() {
+ return $this->contLang;
+ }
+
/**
* Replaces all occurrences of HTML-style comments and the given tags
* in the text with a random marker and returns the next text. The output
$line = "</{$last_tag}>{$line}";
}
array_pop( $tr_attributes );
- $outLine = $line . str_repeat( '</dd></dl>', $indent_level );
+ if ( $indent_level > 0 ) {
+ $outLine = rtrim( $line ) . str_repeat( '</dd></dl>', $indent_level );
+ } else {
+ $outLine = $line;
+ }
} elseif ( $first_two === '|-' ) {
# Now we have a table row
$line = preg_replace( '#^\|-+#', '', $line );
# be mistaken as delimiting cell parameters
# Bug T153140: Neither should language converter markup.
if ( preg_match( '/\[\[|-\{/', $cell_data[0] ) === 1 ) {
- $cell = "{$previous}<{$last_tag}>{$cell}";
+ $cell = "{$previous}<{$last_tag}>" . trim( $cell );
} elseif ( count( $cell_data ) == 1 ) {
- $cell = "{$previous}<{$last_tag}>{$cell_data[0]}";
+ // Whitespace in cells is trimmed
+ $cell = "{$previous}<{$last_tag}>" . trim( $cell_data[0] );
} else {
$attributes = $this->mStripState->unstripBoth( $cell_data[0] );
$attributes = Sanitizer::fixTagAttributes( $attributes, $last_tag );
- $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}";
+ // Whitespace in cells is trimmed
+ $cell = "{$previous}<{$last_tag}{$attributes}>" . trim( $cell_data[1] );
}
$outLine .= $cell;
* @private
*
* @param string $text The text to parse
+ * @param-taint $text escapes_html
* @param bool $isMain Whether this is being called from the main parse() function
* @param PPFrame|bool $frame A pre-processor frame
*
}
# Clean up special characters, only run once, next-to-last before doBlockLevels
- $fixtags = [
- # French spaces, last one Guillemet-left
- # only if there is something before the space
- '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1 ',
- # french spaces, Guillemet-right
- '/(\\302\\253) /' => '\\1 ',
- '/ (!\s*important)/' => ' \\1', # Beware of CSS magic word !important, T13874.
- ];
- $text = preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text );
+ $text = Sanitizer::armorFrenchSpaces( $text );
$text = $this->doBlockLevels( $text, $linestart );
# The position of the convert() call should not be changed. it
# assumes that the links are all replaced and the only thing left
# is the <nowiki> mark.
- $text = $this->getConverterLanguage()->convert( $text );
+ $text = $this->getTargetLanguage()->convert( $text );
}
}
} else {
# attempt to sanitize at least some nesting problems
# (T4702 and quite a few others)
+ # This code path is buggy and deprecated!
+ wfDeprecated( 'disabling tidy', '1.33' );
$tidyregs = [
# ''Something [http://www.cool.com cool''] -->
# <i>Something</i><a href="http://www.cool.com"..><i>cool></i></a>
/**
* @throws MWException
* @param array $m
- * @return HTML|string
+ * @return string HTML
*/
public function magicLinkCallback( $m ) {
if ( isset( $m[1] ) && $m[1] !== '' ) {
if ( $text === false ) {
# Not an image, make a link
$text = Linker::makeExternalLink( $url,
- $this->getConverterLanguage()->markNoConversion( $url, true ),
+ $this->getTargetLanguage()->getConverter()->markNoConversion( $url ),
true, 'free',
$this->getExternalLinkAttribs( $url ), $this->mTitle );
# Register it in the output object...
public function doHeadings( $text ) {
for ( $i = 6; $i >= 1; --$i ) {
$h = str_repeat( '=', $i );
- $text = preg_replace( "/^$h(.+)$h\\s*$/m", "<h$i>\\1</h$i>", $text );
+ // Trim non-newline whitespace from headings
+ // Using \s* will break for: "==\n===\n" and parse as <h2>=</h2>
+ $text = preg_replace( "/^(?:$h)[ \\t]*(.+?)[ \\t]*(?:$h)\\s*$/m", "<h$i>\\1</h$i>", $text );
}
return $text;
}
$dtrail = '';
- # Set linktype for CSS - if URL==text, link is essentially free
- $linktype = ( $text === $url ) ? 'free' : 'text';
+ # Set linktype for CSS
+ $linktype = 'text';
# No link text, e.g. [http://domain.tld/some.link]
if ( $text == '' ) {
list( $dtrail, $trail ) = Linker::splitTrail( $trail );
}
- $text = $this->getConverterLanguage()->markNoConversion( $text );
+ // Excluding protocol-relative URLs may avoid many false positives.
+ if ( preg_match( '/^(?:' . wfUrlProtocolsWithoutProtRel() . ')/', $text ) ) {
+ $text = $this->getTargetLanguage()->getConverter()->markNoConversion( $text );
+ }
$url = Sanitizer::cleanUrl( $url );
* @since 1.21
* @param string|bool $url Optional URL, to extract the domain from for rel =>
* nofollow if appropriate
- * @param Title $title Optional Title, for wgNoFollowNsExceptions lookups
+ * @param Title|null $title Optional Title, for wgNoFollowNsExceptions lookups
* @return string|null Rel attribute for $url
*/
public static function getExternalLinkRel( $url = false, $title = null ) {
* @return string
*/
public static function normalizeLinkUrl( $url ) {
- # First, make sure unsafe characters are encoded
+ # Test for RFC 3986 IPv6 syntax
+ $scheme = '[a-z][a-z0-9+.-]*:';
+ $userinfo = '(?:[a-z0-9\-._~!$&\'()*+,;=:]|%[0-9a-f]{2})*';
+ $ipv6Host = '\\[((?:[0-9a-f:]|%3[0-A]|%[46][1-6])+)\\]';
+ if ( preg_match( "<^(?:{$scheme})?//(?:{$userinfo}@)?{$ipv6Host}(?:[:/?#].*|)$>i", $url, $m ) &&
+ IP::isValid( rawurldecode( $m[1] ) )
+ ) {
+ $isIPv6 = rawurldecode( $m[1] );
+ } else {
+ $isIPv6 = false;
+ }
+
+ # Make sure unsafe characters are encoded
$url = preg_replace_callback( '/[\x00-\x20"<>\[\\\\\]^`{|}\x7F-\xFF]/',
function ( $m ) {
return rawurlencode( $m[0] );
$ret = self::normalizeUrlComponent(
substr( $url, 0, $end ), '"#%<>[\]^`{|}/?' ) . $ret;
+ # Fix IPv6 syntax
+ if ( $isIPv6 !== false ) {
+ $ipv6Host = "%5B({$isIPv6})%5D";
+ $ret = preg_replace(
+ "<^((?:{$scheme})?//(?:{$userinfo}@)?){$ipv6Host}(?=[:/?#]|$)>i",
+ "$1[$2]",
+ $ret
+ );
+ }
+
return $ret;
}
* @private
*/
public function replaceInternalLinks2( &$s ) {
- global $wgExtraInterlanguageLinkPrefixes;
-
static $tc = false, $e1, $e1_img;
# the % is needed to support urlencoded titles as well
if ( !$tc ) {
if ( $useLinkPrefixExtension ) {
# Match the end of a line for a word that's not followed by whitespace,
# e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched
- global $wgContLang;
- $charset = $wgContLang->linkPrefixCharset();
+ $charset = $this->contLang->linkPrefixCharset();
$e2 = "/^((?>.*[^$charset]|))(.+)$/sDu";
}
if (
$iw && $this->mOptions->getInterwikiMagic() && $nottalk && (
Language::fetchLanguageName( $iw, null, 'mw' ) ||
- in_array( $iw, $wgExtraInterlanguageLinkPrefixes )
+ in_array( $iw, $this->siteConfig->get( 'ExtraInterlanguageLinkPrefixes' ) )
)
) {
# T26502: filter duplicates
}
$sortkey = Sanitizer::decodeCharReferences( $sortkey );
$sortkey = str_replace( "\n", '', $sortkey );
- $sortkey = $this->getConverterLanguage()->convertCategoryKey( $sortkey );
+ $sortkey = $this->getTargetLanguage()->convertCategoryKey( $sortkey );
$this->mOutput->addCategory( $nt->getDBkey(), $sortkey );
continue;
*
* @private
*
- * @param string $index Magic variable identifier as mapped in MagicWord::$mVariableIDs
+ * @param string $index Magic variable identifier as mapped in MagicWordFactory::$mVariableIDs
* @param bool|PPFrame $frame
*
* @throws MWException
* @return string
*/
public function getVariableValue( $index, $frame = false ) {
- global $wgContLang, $wgSitename, $wgServer, $wgServerName;
- global $wgArticlePath, $wgScriptPath, $wgStylePath;
-
if ( is_null( $this->mTitle ) ) {
// If no title set, bad things are going to happen
// later. Title should always be set since this
$this->mOutput->setFlag( 'vary-revision' );
wfDebug( __METHOD__ . ": {{PAGEID}} used in a new page, setting vary-revision...\n" );
}
- $value = $pageid ? $pageid : null;
+ $value = $pageid ?: null;
break;
case 'revisionid':
# Let the edit saving system know we should parse the page
$this->mOutput->setFlag( 'vary-revision-id' );
wfDebug( __METHOD__ . ": {{REVISIONID}} used, setting vary-revision-id...\n" );
$value = $this->mRevisionId;
- if ( !$value && $this->mOptions->getSpeculativeRevIdCallback() ) {
- $value = call_user_func( $this->mOptions->getSpeculativeRevIdCallback() );
- $this->mOutput->setSpeculativeRevIdUsed( $value );
+
+ if ( !$value ) {
+ $rev = $this->getRevisionObject();
+ if ( $rev ) {
+ $value = $rev->getId();
+ }
+ }
+
+ if ( !$value ) {
+ $value = $this->mOptions->getSpeculativeRevId();
+ if ( $value ) {
+ $this->mOutput->setSpeculativeRevIdUsed( $value );
+ }
}
break;
case 'revisionday':
- # Let the edit saving system know we should parse the page
- # *after* a revision ID has been assigned. This is for null edits.
- $this->mOutput->setFlag( 'vary-revision' );
- wfDebug( __METHOD__ . ": {{REVISIONDAY}} used, setting vary-revision...\n" );
- $value = intval( substr( $this->getRevisionTimestamp(), 6, 2 ) );
+ $value = (int)$this->getRevisionTimestampSubstring( 6, 2, self::MAX_TTS, $index );
break;
case 'revisionday2':
- # Let the edit saving system know we should parse the page
- # *after* a revision ID has been assigned. This is for null edits.
- $this->mOutput->setFlag( 'vary-revision' );
- wfDebug( __METHOD__ . ": {{REVISIONDAY2}} used, setting vary-revision...\n" );
- $value = substr( $this->getRevisionTimestamp(), 6, 2 );
+ $value = $this->getRevisionTimestampSubstring( 6, 2, self::MAX_TTS, $index );
break;
case 'revisionmonth':
- # Let the edit saving system know we should parse the page
- # *after* a revision ID has been assigned. This is for null edits.
- $this->mOutput->setFlag( 'vary-revision' );
- wfDebug( __METHOD__ . ": {{REVISIONMONTH}} used, setting vary-revision...\n" );
- $value = substr( $this->getRevisionTimestamp(), 4, 2 );
+ $value = $this->getRevisionTimestampSubstring( 4, 2, self::MAX_TTS, $index );
break;
case 'revisionmonth1':
- # Let the edit saving system know we should parse the page
- # *after* a revision ID has been assigned. This is for null edits.
- $this->mOutput->setFlag( 'vary-revision' );
- wfDebug( __METHOD__ . ": {{REVISIONMONTH1}} used, setting vary-revision...\n" );
- $value = intval( substr( $this->getRevisionTimestamp(), 4, 2 ) );
+ $value = (int)$this->getRevisionTimestampSubstring( 4, 2, self::MAX_TTS, $index );
break;
case 'revisionyear':
- # Let the edit saving system know we should parse the page
- # *after* a revision ID has been assigned. This is for null edits.
- $this->mOutput->setFlag( 'vary-revision' );
- wfDebug( __METHOD__ . ": {{REVISIONYEAR}} used, setting vary-revision...\n" );
- $value = substr( $this->getRevisionTimestamp(), 0, 4 );
+ $value = $this->getRevisionTimestampSubstring( 0, 4, self::MAX_TTS, $index );
break;
case 'revisiontimestamp':
# Let the edit saving system know we should parse the page
$value = $this->getRevisionSize();
break;
case 'namespace':
- $value = str_replace( '_', ' ', $wgContLang->getNsText( $this->mTitle->getNamespace() ) );
+ $value = str_replace( '_', ' ',
+ $this->contLang->getNsText( $this->mTitle->getNamespace() ) );
break;
case 'namespacee':
- $value = wfUrlencode( $wgContLang->getNsText( $this->mTitle->getNamespace() ) );
+ $value = wfUrlencode( $this->contLang->getNsText( $this->mTitle->getNamespace() ) );
break;
case 'namespacenumber':
$value = $this->mTitle->getNamespace();
$value = SpecialVersion::getVersion();
break;
case 'articlepath':
- return $wgArticlePath;
+ return $this->siteConfig->get( 'ArticlePath' );
case 'sitename':
- return $wgSitename;
+ return $this->siteConfig->get( 'Sitename' );
case 'server':
- return $wgServer;
+ return $this->siteConfig->get( 'Server' );
case 'servername':
- return $wgServerName;
+ return $this->siteConfig->get( 'ServerName' );
case 'scriptpath':
- return $wgScriptPath;
+ return $this->siteConfig->get( 'ScriptPath' );
case 'stylepath':
- return $wgStylePath;
+ return $this->siteConfig->get( 'StylePath' );
case 'directionmark':
return $pageLang->getDirMark();
case 'contentlanguage':
- global $wgLanguageCode;
- return $wgLanguageCode;
+ return $this->siteConfig->get( 'LanguageCode' );
case 'pagelanguage':
$value = $pageLang->getCode();
break;
return $value;
}
+ /**
+ * @param int $start
+ * @param int $len
+ * @param int $mtts Max time-till-save; sets vary-revision if result might change by then
+ * @param string $variable Parser variable name
+ * @return string
+ */
+ private function getRevisionTimestampSubstring( $start, $len, $mtts, $variable ) {
+ # Get the timezone-adjusted timestamp to be used for this revision
+ $resNow = substr( $this->getRevisionTimestamp(), $start, $len );
+ # Possibly set vary-revision if there is not yet an associated revision
+ if ( !$this->getRevisionObject() ) {
+ # Get the timezone-adjusted timestamp $mtts seconds in the future
+ $resThen = substr(
+ $this->contLang->userAdjust( wfTimestamp( TS_MW, time() + $mtts ), '' ),
+ $start,
+ $len
+ );
+
+ if ( $resNow !== $resThen ) {
+ # Let the edit saving system know we should parse the page
+ # *after* a revision ID has been assigned. This is for null edits.
+ $this->mOutput->setFlag( 'vary-revision' );
+ wfDebug( __METHOD__ . ": $variable used, setting vary-revision...\n" );
+ }
+ }
+
+ return $resNow;
+ }
+
/**
* initialise the magic variables (like CURRENTMONTHNAME) and substitution modifiers
*
* @private
*/
public function initialiseVariables() {
- $variableIDs = MagicWord::getVariableIDs();
- $substIDs = MagicWord::getSubstIDs();
+ $variableIDs = $this->magicWordFactory->getVariableIDs();
+ $substIDs = $this->magicWordFactory->getSubstIDs();
- $this->mVariables = new MagicWordArray( $variableIDs );
- $this->mSubstWords = new MagicWordArray( $substIDs );
+ $this->mVariables = $this->magicWordFactory->newArray( $variableIDs );
+ $this->mSubstWords = $this->magicWordFactory->newArray( $substIDs );
}
/**
* 'expansion-depth-exceeded-category')
* @param string|int|null $current Current value
* @param string|int|null $max Maximum allowed, when an explicit limit has been
- * exceeded, provide the values (optional)
+ * exceeded, provide the values (optional)
*/
public function limitationWarn( $limitationType, $current = '', $max = '' ) {
# does no harm if $current and $max are present but are unnecessary for the message
$id = $this->mVariables->matchStartToEnd( $part1 );
if ( $id !== false ) {
$text = $this->getVariableValue( $id, $frame );
- if ( MagicWord::getCacheTTL( $id ) > -1 ) {
- $this->mOutput->updateCacheExpiry( MagicWord::getCacheTTL( $id ) );
+ if ( $this->magicWordFactory->getCacheTTL( $id ) > -1 ) {
+ $this->mOutput->updateCacheExpiry(
+ $this->magicWordFactory->getCacheTTL( $id ) );
}
$found = true;
}
# MSG, MSGNW and RAW
if ( !$found ) {
# Check for MSGNW:
- $mwMsgnw = MagicWord::get( 'msgnw' );
+ $mwMsgnw = $this->magicWordFactory->get( 'msgnw' );
if ( $mwMsgnw->matchStartAndRemove( $part1 ) ) {
$nowiki = true;
} else {
# Remove obsolete MSG:
- $mwMsg = MagicWord::get( 'msg' );
+ $mwMsg = $this->magicWordFactory->get( 'msg' );
$mwMsg->matchStartAndRemove( $part1 );
}
# Check for RAW:
- $mwRaw = MagicWord::get( 'raw' );
+ $mwRaw = $this->magicWordFactory->get( 'raw' );
if ( $mwRaw->matchStartAndRemove( $part1 ) ) {
$forceRawInterwiki = true;
}
for ( $i = 0; $i < $argsLength; $i++ ) {
$funcArgs[] = $args->item( $i );
}
- try {
- $result = $this->callParserFunction( $frame, $func, $funcArgs );
- } catch ( Exception $ex ) {
- throw $ex;
- }
+
+ $result = $this->callParserFunction( $frame, $func, $funcArgs );
// Extract any forwarded flags
if ( isset( $result['title'] ) ) {
if ( $title ) {
$titleText = $title->getPrefixedText();
# Check for language variants if the template is not found
- if ( $this->getConverterLanguage()->hasVariants() && $title->getArticleID() == 0 ) {
- $this->getConverterLanguage()->findVariantLink( $part1, $title, true );
+ if ( $this->getTargetLanguage()->hasVariants() && $title->getArticleID() == 0 ) {
+ $this->getTargetLanguage()->findVariantLink( $part1, $title, true );
}
# Do recursion depth check
$limit = $this->mOptions->getMaxTemplateDepth();
&& $this->mOptions->getAllowSpecialInclusion()
&& $this->ot['html']
) {
- $specialPage = SpecialPageFactory::getPage( $title->getDBkey() );
+ $specialPage = $this->specialPageFactory->getPage( $title->getDBkey() );
// Pass the template arguments as URL parameters.
// "uselang" will have no effect since the Language object
// is forced to the one defined in ParserOptions.
$context->setUser( User::newFromName( '127.0.0.1', false ) );
}
$context->setLanguage( $this->mOptions->getUserLangObj() );
- $ret = SpecialPageFactory::capturePath(
- $title, $context, $this->getLinkRenderer() );
+ $ret = $this->specialPageFactory->capturePath( $title, $context, $this->getLinkRenderer() );
if ( $ret ) {
$text = $context->getOutput()->getHTML();
$this->mOutput->addOutputPageMetadata( $context->getOutput() );
* @return array
*/
public function callParserFunction( $frame, $function, array $args = [] ) {
- global $wgContLang;
-
# Case sensitive functions
if ( isset( $this->mFunctionSynonyms[1][$function] ) ) {
$function = $this->mFunctionSynonyms[1][$function];
} else {
# Case insensitive functions
- $function = $wgContLang->lc( $function );
+ $function = $this->contLang->lc( $function );
if ( isset( $this->mFunctionSynonyms[0][$function] ) ) {
$function = $this->mFunctionSynonyms[0][$function];
} else {
}
}
- $result = call_user_func_array( $callback, $allArgs );
+ $result = $callback( ...$allArgs );
# The interface for function hooks allows them to return a wikitext
# string or an array containing the string and any flags. This mungs
if ( is_string( $stuff['text'] ) ) {
$text = strtr( $text, "\x7f", "?" );
}
- $finalTitle = isset( $stuff['finalTitle'] ) ? $stuff['finalTitle'] : $title;
+ $finalTitle = $stuff['finalTitle'] ?? $title;
if ( isset( $stuff['deps'] ) ) {
foreach ( $stuff['deps'] as $dep ) {
$this->mOutput->addTemplate( $dep['title'], $dep['page_id'], $dep['rev_id'] );
$rev_id = $rev ? $rev->getId() : 0;
# If there is no current revision, there is no page
if ( $id === false && !$rev ) {
- $linkCache = LinkCache::singleton();
+ $linkCache = MediaWikiServices::getInstance()->getLinkCache();
$linkCache->addBadLinkObj( $title );
}
break;
}
} elseif ( $title->getNamespace() == NS_MEDIAWIKI ) {
- global $wgContLang;
- $message = wfMessage( $wgContLang->lcfirst( $title->getText() ) )->inContentLanguage();
+ $message = wfMessage( MediaWikiServices::getInstance()->getContentLanguage()->
+ lcfirst( $title->getText() ) )->inContentLanguage();
if ( !$message->exists() ) {
$text = false;
break;
* @param Title $title
* @param array $options Array of options to RepoGroup::findFile
* @return File|bool
+ * @deprecated since 1.32, use fetchFileAndTitle instead
*/
public function fetchFile( $title, $options = [] ) {
+ wfDeprecated( __METHOD__, '1.32' );
return $this->fetchFileAndTitle( $title, $options )[0];
}
* Transclude an interwiki link.
*
* @param Title $title
- * @param string $action
+ * @param string $action Usually one of (raw, render)
*
* @return string
*/
public function interwikiTransclude( $title, $action ) {
- global $wgEnableScaryTranscluding;
-
- if ( !$wgEnableScaryTranscluding ) {
+ if ( !$this->siteConfig->get( 'EnableScaryTranscluding' ) ) {
return wfMessage( 'scarytranscludedisabled' )->inContentLanguage()->text();
}
$url = $title->getFullURL( [ 'action' => $action ] );
-
- if ( strlen( $url ) > 255 ) {
+ if ( strlen( $url ) > 1024 ) {
return wfMessage( 'scarytranscludetoolong' )->inContentLanguage()->text();
}
- return $this->fetchScaryTemplateMaybeFromCache( $url );
- }
- /**
- * @param string $url
- * @return mixed|string
- */
- public function fetchScaryTemplateMaybeFromCache( $url ) {
- global $wgTranscludeCacheExpiry;
- $dbr = wfGetDB( DB_REPLICA );
- $tsCond = $dbr->timestamp( time() - $wgTranscludeCacheExpiry );
- $obj = $dbr->selectRow( 'transcache', [ 'tc_time', 'tc_contents' ],
- [ 'tc_url' => $url, "tc_time >= " . $dbr->addQuotes( $tsCond ) ] );
- if ( $obj ) {
- return $obj->tc_contents;
- }
-
- $req = MWHttpRequest::factory( $url, [], __METHOD__ );
- $status = $req->execute(); // Status object
- if ( $status->isOK() ) {
- $text = $req->getContent();
- } elseif ( $req->getStatus() != 200 ) {
+ $wikiId = $title->getTransWikiID(); // remote wiki ID or false
+
+ $fname = __METHOD__;
+ $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+
+ $data = $cache->getWithSetCallback(
+ $cache->makeGlobalKey(
+ 'interwiki-transclude',
+ ( $wikiId !== false ) ? $wikiId : 'external',
+ sha1( $url )
+ ),
+ $this->siteConfig->get( 'TranscludeCacheExpiry' ),
+ function ( $oldValue, &$ttl ) use ( $url, $fname, $cache ) {
+ $req = MWHttpRequest::factory( $url, [], $fname );
+
+ $status = $req->execute(); // Status object
+ if ( !$status->isOK() ) {
+ $ttl = $cache::TTL_UNCACHEABLE;
+ } elseif ( $req->getResponseHeader( 'X-Database-Lagged' ) !== null ) {
+ $ttl = min( $cache::TTL_LAGGED, $ttl );
+ }
+
+ return [
+ 'text' => $status->isOK() ? $req->getContent() : null,
+ 'code' => $req->getStatus()
+ ];
+ },
+ [
+ 'checkKeys' => ( $wikiId !== false )
+ ? [ $cache->makeGlobalKey( 'interwiki-page', $wikiId, $title->getDBkey() ) ]
+ : [],
+ 'pcGroup' => 'interwiki-transclude:5',
+ 'pcTTL' => $cache::TTL_PROC_LONG
+ ]
+ );
+
+ if ( is_string( $data['text'] ) ) {
+ $text = $data['text'];
+ } elseif ( $data['code'] != 200 ) {
// Though we failed to fetch the content, this status is useless.
- return wfMessage( 'scarytranscludefailed-httpstatus' )
- ->params( $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
+ $text = wfMessage( 'scarytranscludefailed-httpstatus' )
+ ->params( $url, $data['code'] )->inContentLanguage()->text();
} else {
- return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
+ $text = wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
}
- $dbw = wfGetDB( DB_MASTER );
- $dbw->replace( 'transcache', [ 'tc_url' ], [
- 'tc_url' => $url,
- 'tc_time' => $dbw->timestamp( time() ),
- 'tc_contents' => $text
- ] );
return $text;
}
*/
public function doDoubleUnderscore( $text ) {
# The position of __TOC__ needs to be recorded
- $mw = MagicWord::get( 'toc' );
+ $mw = $this->magicWordFactory->get( 'toc' );
if ( $mw->match( $text ) ) {
$this->mShowToc = true;
$this->mForceTocPosition = true;
}
# Now match and remove the rest of them
- $mwa = MagicWord::getDoubleUnderscoreArray();
+ $mwa = $this->magicWordFactory->getDoubleUnderscoreArray();
$this->mDoubleUnderscores = $mwa->matchAndRemove( $text );
if ( isset( $this->mDoubleUnderscores['nogallery'] ) ) {
* @private
*/
public function formatHeadings( $text, $origText, $isMain = true ) {
- global $wgMaxTocLevel;
-
# Inhibit editsection links if requested in the page
if ( isset( $this->mDoubleUnderscores['noeditsection'] ) ) {
$maybeShowEditLink = false;
# Get all headlines for numbering them and adding funky stuff like [edit]
# links - this is for later, but we need the number of headlines right now
+ # NOTE: white space in headings have been trimmed in doHeadings. They shouldn't
+ # be trimmed here since whitespace in HTML headings is significant.
$matches = [];
$numMatches = preg_match_all(
- '/<H(?P<level>[1-6])(?P<attrib>.*?>)\s*(?P<header>[\s\S]*?)\s*<\/H[1-6] *>/i',
+ '/<H(?P<level>[1-6])(?P<attrib>.*?>)(?P<header>[\s\S]*?)<\/H[1-6] *>/i',
$text,
$matches
);
$headlines = $numMatches !== false ? $matches[3] : [];
+ $maxTocLevel = $this->siteConfig->get( 'MaxTocLevel' );
foreach ( $headlines as $headline ) {
$isTemplate = false;
$titleText = false;
# Increase TOC level
$toclevel++;
$sublevelCount[$toclevel] = 0;
- if ( $toclevel < $wgMaxTocLevel ) {
+ if ( $toclevel < $maxTocLevel ) {
$prevtoclevel = $toclevel;
$toc .= Linker::tocIndent();
$numVisible++;
if ( $i == 0 ) {
$toclevel = 1;
}
- if ( $toclevel < $wgMaxTocLevel ) {
- if ( $prevtoclevel < $wgMaxTocLevel ) {
+ if ( $toclevel < $maxTocLevel ) {
+ if ( $prevtoclevel < $maxTocLevel ) {
# Unindent only if the previous toc level was shown :p
$toc .= Linker::tocUnindent( $prevtoclevel - $toclevel );
$prevtoclevel = $toclevel;
}
} else {
# No change in level, end TOC line
- if ( $toclevel < $wgMaxTocLevel ) {
+ if ( $toclevel < $maxTocLevel ) {
$toc .= Linker::tocLineEnd();
}
}
# Avoid insertion of weird stuff like <math> by expanding the relevant sections
$safeHeadline = $this->mStripState->unstripBoth( $safeHeadline );
+ # Remove any <style> or <script> tags (T198618)
+ $safeHeadline = preg_replace(
+ '#<(style|script)(?: [^>]*[^>/])?>.*?</\1>#is',
+ '',
+ $safeHeadline
+ );
+
# Strip out HTML (first regex removes any tag not allowed)
# Allowed tags are:
# * <sup> and <sub> (T10393)
) . ' ' . $headline;
}
- if ( $enoughToc && ( !isset( $wgMaxTocLevel ) || $toclevel < $wgMaxTocLevel ) ) {
+ if ( $enoughToc && ( !isset( $maxTocLevel ) || $toclevel < $maxTocLevel ) ) {
$toc .= Linker::tocLine( $linkAnchor, $tocline,
$numbering, $toclevel, ( $isTemplate ? false : $sectionIndex ) );
}
}
if ( $enoughToc ) {
- if ( $prevtoclevel > 0 && $prevtoclevel < $wgMaxTocLevel ) {
+ if ( $prevtoclevel > 0 && $prevtoclevel < $maxTocLevel ) {
$toc .= Linker::tocUnindent( $prevtoclevel - 1 );
}
$toc = Linker::tocList( $toc, $this->mOptions->getUserLangObj() );
* @return string
*/
private function pstPass2( $text, $user ) {
- global $wgContLang;
-
- # Note: This is the timestamp saved as hardcoded wikitext to
- # the database, we use $wgContLang here in order to give
- # everyone the same signature and use the default one rather
- # than the one selected in each user's preferences.
- # (see also T14815)
+ # Note: This is the timestamp saved as hardcoded wikitext to the database, we use
+ # $this->contLang here in order to give everyone the same signature and use the default one
+ # rather than the one selected in each user's preferences. (see also T14815)
$ts = $this->mOptions->getTimestamp();
$timestamp = MWTimestamp::getLocalInstance( $ts );
$ts = $timestamp->format( 'YmdHis' );
$tzMsg = $timestamp->getTimezoneMessage()->inContentLanguage()->text();
- $d = $wgContLang->timeanddate( $ts, false, false ) . " ($tzMsg)";
+ $d = $this->contLang->timeanddate( $ts, false, false ) . " ($tzMsg)";
# Variable replacement
# Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags
* @return string
*/
public function getUserSig( &$user, $nickname = false, $fancySig = null ) {
- global $wgMaxSigChars;
-
$username = $user->getName();
# If not given, retrieve from the user object.
$nickname = $nickname == null ? $username : $nickname;
- if ( mb_strlen( $nickname ) > $wgMaxSigChars ) {
+ if ( mb_strlen( $nickname ) > $this->siteConfig->get( 'MaxSigChars' ) ) {
$nickname = $username;
wfDebug( __METHOD__ . ": $username has overlong signature.\n" );
} elseif ( $fancySig !== false ) {
# @todo FIXME: Regex doesn't respect extension tags or nowiki
# => Move this logic to braceSubstitution()
- $substWord = MagicWord::get( 'subst' );
+ $substWord = $this->magicWordFactory->get( 'subst' );
$substRegex = '/\{\{(?!(?:' . $substWord->getBaseRegex() . '))/x' . $substWord->getRegexCase();
$substText = '{{' . $substWord->getSynonym( 0 );
if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
throw new MWException( "Invalid character {$m[0]} in setHook('$tag', ...) call" );
}
- $oldVal = isset( $this->mTagHooks[$tag] ) ? $this->mTagHooks[$tag] : null;
+ $oldVal = $this->mTagHooks[$tag] ?? null;
$this->mTagHooks[$tag] = $callback;
if ( !in_array( $tag, $this->mStripList ) ) {
$this->mStripList[] = $tag;
if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
throw new MWException( "Invalid character {$m[0]} in setTransparentHook('$tag', ...) call" );
}
- $oldVal = isset( $this->mTransparentTagHooks[$tag] ) ? $this->mTransparentTagHooks[$tag] : null;
+ $oldVal = $this->mTransparentTagHooks[$tag] ?? null;
$this->mTransparentTagHooks[$tag] = $callback;
return $oldVal;
* @return string|callable The old callback function for this name, if any
*/
public function setFunctionHook( $id, callable $callback, $flags = 0 ) {
- global $wgContLang;
-
$oldVal = isset( $this->mFunctionHooks[$id] ) ? $this->mFunctionHooks[$id][0] : null;
$this->mFunctionHooks[$id] = [ $callback, $flags ];
# Add to function cache
- $mw = MagicWord::get( $id );
+ $mw = $this->magicWordFactory->get( $id );
if ( !$mw ) {
throw new MWException( __METHOD__ . '() expecting a magic word identifier.' );
}
foreach ( $synonyms as $syn ) {
# Case
if ( !$sensitive ) {
- $syn = $wgContLang->lc( $syn );
+ $syn = $this->contLang->lc( $syn );
}
# Add leading hash
if ( !( $flags & self::SFH_NO_HASH ) ) {
* @return array
*/
public function getFunctionHooks() {
+ $this->firstCallInit();
return array_keys( $this->mFunctionHooks );
}
if ( preg_match( '/[<>\r\n]/', $tag, $m ) ) {
throw new MWException( "Invalid character {$m[0]} in setFunctionTagHook('$tag', ...) call" );
}
- $old = isset( $this->mFunctionTagHooks[$tag] ) ?
- $this->mFunctionTagHooks[$tag] : null;
+ $old = $this->mFunctionTagHooks[$tag] ?? null;
$this->mFunctionTagHooks[$tag] = [ $callback, $flags ];
if ( !in_array( $tag, $this->mStripList ) ) {
$ig->setShowFilename( false );
}
if ( isset( $params['caption'] ) ) {
- $caption = $params['caption'];
- $caption = htmlspecialchars( $caption );
- $caption = $this->replaceInternalLinks( $caption );
+ // NOTE: We aren't passing a frame here or below. Frame info
+ // is currently opaque to Parsoid, which acts on OT_PREPROCESS.
+ // See T107332#4030581
+ $caption = $this->recursiveTagParse( $params['caption'] );
$ig->setCaptionHtml( $caption );
}
if ( isset( $params['perrow'] ) ) {
unset( $paramMap['img_width'] );
}
- $mwArray = new MagicWordArray( array_keys( $paramMap ) );
+ $mwArray = $this->magicWordFactory->newArray( array_keys( $paramMap ) );
$label = '';
$alt = '';
$alt = $this->stripAltText( $match, false );
break;
case 'gallery-internal-link':
- $linkValue = strip_tags( $this->replaceLinkHoldersText( $match ) );
- $chars = self::EXT_LINK_URL_CLASS;
- $addr = self::EXT_LINK_ADDR;
- $prots = $this->mUrlProtocols;
- // check to see if link matches an absolute url, if not then it must be a wiki link.
+ $linkValue = $this->stripAltText( $match, false );
if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
// Result of LanguageConverter::markNoConversion
// invoked on an external link.
$linkValue = substr( $linkValue, 4, -2 );
}
- if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
- $link = $linkValue;
- $this->mOutput->addExternalLink( $link );
- } else {
- $localLinkTitle = Title::newFromText( $linkValue );
- if ( $localLinkTitle !== null ) {
- $this->mOutput->addLink( $localLinkTitle );
- $link = $localLinkTitle->getLinkURL();
- }
+ list( $type, $target ) = $this->parseLinkParameter( $linkValue );
+ if ( $type === 'link-url' ) {
+ $link = $target;
+ $this->mOutput->addExternalLink( $target );
+ } elseif ( $type === 'link-title' ) {
+ $link = $target->getLinkURL();
+ $this->mOutput->addLink( $target );
}
break;
default:
} else {
// Guess not, consider it as caption.
wfDebug( "$parameterMatch failed parameter validation\n" );
- $label = '|' . $parameterMatch;
+ $label = $parameterMatch;
}
}
} else {
// Last pipe wins.
- $label = '|' . $parameterMatch;
+ $label = $parameterMatch;
}
}
- // Remove the pipe.
- $label = substr( $label, 1 );
}
$ig->add( $title, $label, $alt, $link, $handlerOptions );
}
}
$this->mImageParams[$handlerClass] = $paramMap;
- $this->mImageParamsMagicArray[$handlerClass] = new MagicWordArray( array_keys( $paramMap ) );
+ $this->mImageParamsMagicArray[$handlerClass] =
+ $this->magicWordFactory->newArray( array_keys( $paramMap ) );
}
return [ $this->mImageParams[$handlerClass], $this->mImageParamsMagicArray[$handlerClass] ];
}
# * bottom
# * text-bottom
+ global $wgMediaInTargetLanguage;
+
# Protect LanguageConverter markup when splitting into parts
$parts = StringUtils::delimiterExplode(
'-{', '}-', '|', $options, true /* allow nesting */
$value = $this->stripAltText( $value, $holders );
break;
case 'link':
- $chars = self::EXT_LINK_URL_CLASS;
- $addr = self::EXT_LINK_ADDR;
- $prots = $this->mUrlProtocols;
- if ( $value === '' ) {
- $paramName = 'no-link';
- $value = true;
+ list( $paramName, $value ) =
+ $this->parseLinkParameter(
+ $this->stripAltText( $value, $holders )
+ );
+ if ( $paramName ) {
$validated = true;
- } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
- if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
- $paramName = 'link-url';
- $this->mOutput->addExternalLink( $value );
+ if ( $paramName === 'no-link' ) {
+ $value = true;
+ }
+ if ( $paramName === 'link-url' ) {
if ( $this->mOptions->getExternalLinkTarget() ) {
$params[$type]['link-target'] = $this->mOptions->getExternalLinkTarget();
}
- $validated = true;
- }
- } else {
- $linkTitle = Title::newFromText( $value );
- if ( $linkTitle ) {
- $paramName = 'link-title';
- $value = $linkTitle;
- $this->mOutput->addLink( $linkTitle );
- $validated = true;
}
}
break;
# Use the "caption" for the tooltip text
$params['frame']['title'] = $this->stripAltText( $caption, $holders );
}
+ if ( $wgMediaInTargetLanguage ) {
+ $params['handler']['targetlang'] = $this->getTargetLanguage()->getCode();
+ }
Hooks::run( 'ParserMakeImageParams', [ $title, $file, &$params, $this ] );
# Linker does the rest
- $time = isset( $options['time'] ) ? $options['time'] : false;
+ $time = $options['time'] ?? false;
$ret = Linker::makeImageLink( $this, $title, $file, $params['frame'], $params['handler'],
$time, $descQuery, $this->mOptions->getThumbSize() );
return $ret;
}
+ /**
+ * Parse the value of 'link' parameter in image syntax (`[[File:Foo.jpg|link=<value>]]`).
+ *
+ * Adds an entry to appropriate link tables.
+ *
+ * @since 1.32
+ * @return array of `[ type, target ]`, where:
+ * - `type` is one of:
+ * - `null`: Given value is not a valid link target, use default
+ * - `'no-link'`: Given value is empty, do not generate a link
+ * - `'link-url'`: Given value is a valid external link
+ * - `'link-title'`: Given value is a valid internal link
+ * - `target` is:
+ * - When `type` is `null` or `'no-link'`: `false`
+ * - When `type` is `'link-url'`: URL string corresponding to given value
+ * - When `type` is `'link-title'`: Title object corresponding to given value
+ */
+ public function parseLinkParameter( $value ) {
+ $chars = self::EXT_LINK_URL_CLASS;
+ $addr = self::EXT_LINK_ADDR;
+ $prots = $this->mUrlProtocols;
+ $type = null;
+ $target = false;
+ if ( $value === '' ) {
+ $type = 'no-link';
+ } elseif ( preg_match( "/^((?i)$prots)/", $value ) ) {
+ if ( preg_match( "/^((?i)$prots)$addr$chars*$/u", $value, $m ) ) {
+ $this->mOutput->addExternalLink( $value );
+ $type = 'link-url';
+ $target = $value;
+ }
+ } else {
+ $linkTitle = Title::newFromText( $value );
+ if ( $linkTitle ) {
+ $this->mOutput->addLink( $linkTitle );
+ $type = 'link-title';
+ $target = $linkTitle;
+ }
+ }
+ return [ $type, $target ];
+ }
+
/**
* @param string $caption
* @param LinkHolderArray|bool $holders
# that are later expanded to html- so expand them now and
# remove the tags
$tooltip = $this->mStripState->unstripBoth( $tooltip );
+ # Compatibility hack! In HTML certain entity references not terminated
+ # by a semicolon are decoded (but not if we're in an attribute; that's
+ # how link URLs get away without properly escaping & in queries).
+ # But wikitext has always required semicolon-termination of entities,
+ # so encode & where needed to avoid decode of semicolon-less entities.
+ # See T209236 and
+ # https://www.w3.org/TR/html5/syntax.html#named-character-references
+ # T210437 discusses moving this workaround to Sanitizer::stripAllTags.
+ $tooltip = preg_replace( "/
+ & # 1. entity prefix
+ (?= # 2. followed by:
+ (?: # a. one of the legacy semicolon-less named entities
+ A(?:Elig|MP|acute|circ|grave|ring|tilde|uml)|
+ C(?:OPY|cedil)|E(?:TH|acute|circ|grave|uml)|
+ GT|I(?:acute|circ|grave|uml)|LT|Ntilde|
+ O(?:acute|circ|grave|slash|tilde|uml)|QUOT|REG|THORN|
+ U(?:acute|circ|grave|uml)|Yacute|
+ a(?:acute|c(?:irc|ute)|elig|grave|mp|ring|tilde|uml)|brvbar|
+ c(?:cedil|edil|urren)|cent(?!erdot;)|copy(?!sr;)|deg|
+ divide(?!ontimes;)|e(?:acute|circ|grave|th|uml)|
+ frac(?:1(?:2|4)|34)|
+ gt(?!c(?:c|ir)|dot|lPar|quest|r(?:a(?:pprox|rr)|dot|eq(?:less|qless)|less|sim);)|
+ i(?:acute|circ|excl|grave|quest|uml)|laquo|
+ lt(?!c(?:c|ir)|dot|hree|imes|larr|quest|r(?:Par|i(?:e|f|));)|
+ m(?:acr|i(?:cro|ddot))|n(?:bsp|tilde)|
+ not(?!in(?:E|dot|v(?:a|b|c)|)|ni(?:v(?:a|b|c)|);)|
+ o(?:acute|circ|grave|rd(?:f|m)|slash|tilde|uml)|
+ p(?:lusmn|ound)|para(?!llel;)|quot|r(?:aquo|eg)|
+ s(?:ect|hy|up(?:1|2|3)|zlig)|thorn|times(?!b(?:ar|)|d;)|
+ u(?:acute|circ|grave|ml|uml)|y(?:acute|en|uml)
+ )
+ (?:[^;]|$)) # b. and not followed by a semicolon
+ # S = study, for efficiency
+ /Sx", '&', $tooltip );
$tooltip = Sanitizer::stripAllTags( $tooltip );
return $tooltip;
* @return array
*/
public function getTags() {
+ $this->firstCallInit();
return array_merge(
array_keys( $this->mTransparentTagHooks ),
array_keys( $this->mTagHooks ),
);
}
+ /**
+ * @since 1.32
+ * @return array
+ */
+ public function getFunctionSynonyms() {
+ $this->firstCallInit();
+ return $this->mFunctionSynonyms;
+ }
+
+ /**
+ * @since 1.32
+ * @return string
+ */
+ public function getUrlProtocols() {
+ return $this->mUrlProtocols;
+ }
+
/**
* Replace transparent tags in $text with the values given by the callbacks.
*
if ( !is_null( $this->mRevisionObject ) ) {
return $this->mRevisionObject;
}
- if ( is_null( $this->mRevisionId ) ) {
- return null;
- }
+ // NOTE: try to get the RevisionObject even if mRevisionId is null.
+ // This is useful when parsing revision that has not yet been saved.
+ // However, if we get back a saved revision even though we are in
+ // preview mode, we'll have to ignore it, see below.
+ // NOTE: This callback may be used to inject an OLD revision that was
+ // already loaded, so "current" is a bit of a misnomer. We can't just
+ // skip it if mRevisionId is set.
$rev = call_user_func(
$this->mOptions->getCurrentRevisionCallback(), $this->getTitle(), $this
);
- # If the parse is for a new revision, then the callback should have
- # already been set to force the object and should match mRevisionId.
- # If not, try to fetch by mRevisionId for sanity.
- if ( $rev && $rev->getId() != $this->mRevisionId ) {
+ if ( $this->mRevisionId === null && $rev && $rev->getId() ) {
+ // We are in preview mode (mRevisionId is null), and the current revision callback
+ // returned an existing revision. Ignore it and return null, it's probably the page's
+ // current revision, which is not what we want here. Note that we do want to call the
+ // callback to allow the unsaved revision to be injected here, e.g. for
+ // self-transclusion previews.
+ return null;
+ }
+
+ // If the parse is for a new revision, then the callback should have
+ // already been set to force the object and should match mRevisionId.
+ // If not, try to fetch by mRevisionId for sanity.
+ if ( $this->mRevisionId && $rev && $rev->getId() != $this->mRevisionId ) {
$rev = Revision::newFromId( $this->mRevisionId );
}
*/
public function getRevisionTimestamp() {
if ( is_null( $this->mRevisionTimestamp ) ) {
- global $wgContLang;
-
$revObject = $this->getRevisionObject();
$timestamp = $revObject ? $revObject->getTimestamp() : wfTimestampNow();
# Since this value will be saved into the parser cache, served
# to other users, and potentially even used inside links and such,
# it needs to be consistent for all visitors.
- $this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp, '' );
-
+ $this->mRevisionTimestamp = $this->contLang->userAdjust( $timestamp, '' );
}
return $this->mRevisionTimestamp;
}
return '#' . Sanitizer::escapeIdForLink( $sectionName );
}
- private static function makeLegacyAnchor( $sectionName ) {
- global $wgFragmentMode;
- if ( isset( $wgFragmentMode[1] ) && $wgFragmentMode[1] === 'legacy' ) {
+ private function makeLegacyAnchor( $sectionName ) {
+ $fragmentMode = $this->siteConfig->get( 'FragmentMode' );
+ if ( isset( $fragmentMode[1] ) && $fragmentMode[1] === 'legacy' ) {
// ForAttribute() and ForLink() are the same for legacy encoding
$id = Sanitizer::escapeIdForAttribute( $sectionName, Sanitizer::ID_FALLBACK );
} else {
# Strip out wikitext links(they break the anchor)
$text = $this->stripSectionName( $text );
$sectionName = self::getSectionNameFromStrippedText( $text );
- return self::makeLegacyAnchor( $sectionName );
+ return $this->makeLegacyAnchor( $sectionName );
}
/**
* @return Parser A parser object that is not parsing anything
*/
public function getFreshParser() {
- global $wgParserConf;
if ( $this->mInParse ) {
- return new $wgParserConf['class']( $wgParserConf );
+ return $this->factory->create();
} else {
return $this;
}
# You can also set the following parser properties via test options:
# wgEnableUploads, wgAllowExternalImages, wgMaxTocLevel,
# wgLinkHolderBatchSize, wgRawHtml, wgInterwikiMagic,
-# wgEnableMagicLinks
+# wgEnableMagicLinks, wgMediaInTargetLanguage
#
# For testing purposes, temporary articles can created:
# !!article / NAMESPACE:TITLE / !!text / ARTICLE TEXT / !!endarticle
FOO
!!endarticle
+!!article
+Foo''s bar''s
+!!text
+Article titles can contain single quotes!
+!!endarticle
+
!!article
Template:Foo
!!text
FOO
!!endarticle
+!! article
+Template:redirect to foo
+!! text
+#REDIRECT [[Template:Foo]]
+!! endarticle
+
!! article
Template:Blank
!! text
{{{1}}}
!! endarticle
+!! article
+Template:echo3
+!! text
+{{{1}}}
+{{{1}}}
+{{{1}}}
+!! endarticle
+
// For Serbian; localize Template namespace
!! article
Шаблон:Echo
<div>{{{1}}}</div>
!! endarticle
+!! article
+Template:echo with depth
+!! text
+{{echo|{{{1}}}}}
+!! endarticle
+
!! article
Template:blank_param
!! text
!!article
Template:Bullet
!!text
-* Bar
+*Bar
!!endarticle
!!article
!! test
Paragraphs with extra newline spacing
!! wikitext
-foo
+a
-bar
+b (+2 nls)
-baz
+c (+3 nls)
+
+d (+4 nls)
-booz
+
+
+
+e (+5 nls)
!! html
-<p>foo
-</p><p>bar
+<p>a
+</p><p>b (+2 nls)
</p><p><br />
-baz
+c (+3 nls)
+</p><p><br />
+</p><p>d (+4 nls)
</p><p><br />
-</p><p>booz
+</p><p><br />
+e (+5 nls)
</p>
!! end
a
-
=b=
[[a]]
!! end
!! test
-Extra newlines between heading and content are swallowed
+Extra newlines between heading and content are swallowed (Parsoid does not)
!! wikitext
=b=
[[a]]
-!! html
+!! html/php+tidy
<h1><span class="mw-headline" id="b">b</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: b">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
<p><a href="/index.php?title=A&action=edit&redlink=1" class="new" title="A (page does not exist)">a</a>
</p>
+!! html/parsoid
+<h1 id="b">b</h1>
+<p>
+<br></p>
+
+<p><a rel="mw:WikiLink" href="./A" title="A">a</a></p>
+!! end
+
+!! test
+Extra new lines before and after lists are preserved
+!! wikitext
+a
+
+
+*b
+
+
+c
+!! html/php+tidy
+<p>a
+</p><p><br />
+</p>
+<ul><li>b</li></ul>
+<p><br />
+c
+</p>
+!! html/parsoid
+<p>a</p>
+<p>
+<br></p>
+<ul><li>b</li></ul>
+<p>
+<br>
+c</p>
!! end
+# Parsoid regression test
+!!test
+Multiple newlines after tables are converted to p-br-p tags
+!!options
+parsoid=wt2html,wt2wt
+!!wikitext
+{|
+|x
+|}
+
+
+
+
+=b=
+!!html/php+tidy
+<table>
+<tbody><tr>
+<td>x
+</td></tr></tbody></table>
+<p><br />
+</p><p><br />
+</p>
+<h1><span class="mw-headline" id="b">b</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: b">edit</a><span class="mw-editsection-bracket">]</span></span></h1>
+!!html/parsoid
+<table>
+<tbody>
+<tr>
+<td>x</td>
+</tr>
+</tbody>
+</table>
+<p><br/></p>
+<p><br/></p>
+<h1 id="b">b</h1>
+!!end
+
!! test
Heading with line break in nowiki
!! options
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
-== A <nowiki>B
-C</nowiki> ==
+==A <nowiki>B
+C</nowiki>==
!! html/php
<h2><span id="A_B.0AC"></span><span class="mw-headline" id="A_B
C">A B
!! html/parsoid
<h2 id="A_B
-C"><span id="A_B.0AC" typeof="mw:FallbackId"></span> A <span typeof="mw:Nowiki">B
-C</span> </h2>
+C"><span id="A_B.0AC" typeof="mw:FallbackId"></span>A <span typeof="mw:Nowiki">B
+C</span></h2>
!! end
!! test
!! test
Simple list
!! wikitext
-* Item 1
-* Item 2
+*Item 1
+*Item 2
!! html
-<ul><li> Item 1</li>
-<li> Item 2</li></ul>
+<ul><li>Item 1</li>
+<li>Item 2</li></ul>
!! end
!! test
Italics and bold
!! wikitext
-* plain
-* plain''italic''plain
-* plain''italic''plain''italic''plain
-* plain'''bold'''plain
-* plain'''bold'''plain'''bold'''plain
-* plain''italic''plain'''bold'''plain
-* plain'''bold'''plain''italic''plain
-* plain''italic'''bold-italic'''italic''plain
-* plain'''bold''bold-italic''bold'''plain
-* plain'''''bold-italic'''italic''plain
-* plain'''''bold-italic''bold'''plain
-* plain''italic'''bold-italic'''''plain
-* plain'''bold''bold-italic'''''plain
-* plain l'''italic''plain
-* plain l''''bold''' plain
-!! html
-<ul><li> plain</li>
-<li> plain<i>italic</i>plain</li>
-<li> plain<i>italic</i>plain<i>italic</i>plain</li>
-<li> plain<b>bold</b>plain</li>
-<li> plain<b>bold</b>plain<b>bold</b>plain</li>
-<li> plain<i>italic</i>plain<b>bold</b>plain</li>
-<li> plain<b>bold</b>plain<i>italic</i>plain</li>
-<li> plain<i>italic<b>bold-italic</b>italic</i>plain</li>
-<li> plain<b>bold<i>bold-italic</i>bold</b>plain</li>
-<li> plain<i><b>bold-italic</b>italic</i>plain</li>
-<li> plain<b><i>bold-italic</i>bold</b>plain</li>
-<li> plain<i>italic<b>bold-italic</b></i>plain</li>
-<li> plain<b>bold<i>bold-italic</i></b>plain</li>
-<li> plain l'<i>italic</i>plain</li>
-<li> plain l'<b>bold</b> plain</li></ul>
+*plain
+*plain''italic''plain
+*plain''italic''plain''italic''plain
+*plain'''bold'''plain
+*plain'''bold'''plain'''bold'''plain
+*plain''italic''plain'''bold'''plain
+*plain'''bold'''plain''italic''plain
+*plain''italic'''bold-italic'''italic''plain
+*plain'''bold''bold-italic''bold'''plain
+*plain'''''bold-italic'''italic''plain
+*plain'''''bold-italic''bold'''plain
+*plain''italic'''bold-italic'''''plain
+*plain'''bold''bold-italic'''''plain
+*plain l'''italic''plain
+*plain l''''bold''' plain
+!! html
+<ul><li>plain</li>
+<li>plain<i>italic</i>plain</li>
+<li>plain<i>italic</i>plain<i>italic</i>plain</li>
+<li>plain<b>bold</b>plain</li>
+<li>plain<b>bold</b>plain<b>bold</b>plain</li>
+<li>plain<i>italic</i>plain<b>bold</b>plain</li>
+<li>plain<b>bold</b>plain<i>italic</i>plain</li>
+<li>plain<i>italic<b>bold-italic</b>italic</i>plain</li>
+<li>plain<b>bold<i>bold-italic</i>bold</b>plain</li>
+<li>plain<i><b>bold-italic</b>italic</i>plain</li>
+<li>plain<b><i>bold-italic</i>bold</b>plain</li>
+<li>plain<i>italic<b>bold-italic</b></i>plain</li>
+<li>plain<b>bold<i>bold-italic</i></b>plain</li>
+<li>plain l'<i>italic</i>plain</li>
+<li>plain l'<b>bold</b> plain</li></ul>
!! end
!! test
Ruby markup (W3C-style)
!! wikitext
-; Mono-ruby for individual base characters
-: <ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby>
-; Group ruby
-: <ruby>今日<rt>きょう</rt></ruby>
-; Jukugo ruby
-: <ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby>
-; Inline ruby
-: <ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby>
-; Double-sided ruby
-: <ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby>
+;Mono-ruby for individual base characters
+:<ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby>
+;Group ruby
+:<ruby>今日<rt>きょう</rt></ruby>
+;Jukugo ruby
+:<ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby>
+;Inline ruby
+:<ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby>
+;Double-sided ruby
+:<ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby>
+
<ruby>
<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang="fr"><rt>Cœur</rt></rtc>
<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang="fr"><rt>Trèfle</rt></rtc>
<rb>✶</rb><rtc><rt>Star</rt></rtc><rtc lang="fr"><rt>Étoile</rt></rtc>
</ruby>
!! html
-<dl><dt> Mono-ruby for individual base characters</dt>
-<dd> <ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby></dd>
-<dt> Group ruby</dt>
-<dd> <ruby>今日<rt>きょう</rt></ruby></dd>
-<dt> Jukugo ruby</dt>
-<dd> <ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby></dd>
-<dt> Inline ruby</dt>
-<dd> <ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby></dd>
-<dt> Double-sided ruby</dt>
-<dd> <ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby></dd></dl>
+<dl><dt>Mono-ruby for individual base characters</dt>
+<dd><ruby>日<rt>に</rt>本<rt>ほん</rt>語<rt>ご</rt></ruby></dd>
+<dt>Group ruby</dt>
+<dd><ruby>今日<rt>きょう</rt></ruby></dd>
+<dt>Jukugo ruby</dt>
+<dd><ruby>法<rb>華</rb><rb>経</rb><rt>ほ</rt><rt>け</rt><rt>きょう</rt></ruby></dd>
+<dt>Inline ruby</dt>
+<dd><ruby>東<rb>京</rb><rp>(</rp><rt>とう</rt><rt>きょう</rt><rp>)</rp></ruby></dd>
+<dt>Double-sided ruby</dt>
+<dd><ruby><rb>旧</rb><rb>金</rb><rb>山</rb><rt>jiù</rt><rt>jīn</rt><rt>shān</rt><rtc>San Francisco</rtc></ruby></dd></dl>
<p><ruby>
<rb>♥</rb><rtc><rt>Heart</rt></rtc><rtc lang="fr"><rt>Cœur</rt></rtc>
<rb>☘</rb><rtc><rt>Shamrock</rt></rtc><rtc lang="fr"><rt>Trèfle</rt></rtc>
<s.foo> doesn't terminate </s.foo>
<sub-ID#1>
-!! html
+!! html/php
<p><blockquote|>a</blockquote>
</p><p><b→> doesn't terminate </b→>
</p><p><bä> doesn't terminate </bä>
!! end
###
-### See tests/parser/parserTestsParserHook.php for the <tåg> extension)
+### See tests/parser/ParserTestParserHook.php for the <tåg> extension)
### This checks that HTML5 tags (with non-word characters in the tag
### name) make it safely through the parser -- the Sanitizer will
### munge them later, as it should.
</b>
<s.foo>s</s>
-!! html/php+tidy
+!! html+tidy
<p class="mw-empty-elt">
</p><p><s.foo>s
</p>
-!! html/parsoid
-<p><s.foo>s</p>
!! end
###
</p>
!! end
+!! test
+post-expand include size being exceeded
+!! options
+maxincludesize=20
+!! wikitext
+{{echo3|1234567890}}
+!! html
+<p><a href="/wiki/Template:Echo3" title="Template:Echo3">Template:Echo3</a><!-- WARNING: template omitted, post-expand include size too large -->
+</p>
+!! end
+
+!! test
+max template depth being reached
+!! options
+maxtemplatedepth=1
+!! wikitext
+{{echo with depth|too deep!}}
+!! html
+<p><span class="error">Template recursion depth limit exceeded (1)</span>
+</p>
+!! end
+
+!! test
+multiple templates that are redirects
+!! wikitext
+{{redirect to foo}}
+{{redirect to foo}}
+!! html
+<p>FOO
+FOO
+</p>
+!! end
+
!! test
Multiple comments should still parse as SOL-transparent
!! options
</p>
!! end
-# Remex wraps empty tag runs with p-tags.
-# Parsoid strips them out during p-wrapping.
!! test
No p-wrappable content
+!! options
+parsoid=wt2html,html2html
!! wikitext
<span><div>x</div></span>
<span><s><div>x</div></s></span>
<small><em></em></small><span><s><div>x</div></s></span>
-!! html/php+tidy
+!! html+tidy
<span><div>x</div></span>
<span><s><div>x</div></s></span>
<p><small><em></em></small></p><span><s><div>x</div></s></span>
-!! html/parsoid
-<span><div>x</div></span>
-<span><s><div>x</div></s></span>
-<small><em></em></small><span><s><div>x</div></s></span>
!! end
# T177612: Parsoid-only test
</p>
!! end
-# The difference between Parsoid & Remex here
-# is because of Parsoid's Tidy-emulation code
-# for p-wrapping. We'll start work to remove this
-# emulation code in Parsoid sooner than later.
-# Remex wraps empty tag runs with p-tags.
-# Parsoid strips them out in a separate pass.
!! test
Empty lines between lines with block tags
!! wikitext
<link rel="mw:PageProp/Category" href="./Category:Ho" />
!! end
+!! test
+Paragraph wrapping following unclosed table
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+{|
+|-
+
+{|
+| x
+|}
+
+a
+
+b
+
+c
+!! html/php+tidy
+<table>
+
+
+</table><table>
+<tbody><tr>
+<td>x
+</td></tr></tbody></table>
+<p>a
+</p><p>b
+</p><p>c
+</p>
+!! html/parsoid
+<table data-parsoid='{"autoInsertedEnd":true}'>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr>
+
+</tbody></table><table>
+<tbody><tr data-parsoid='{"autoInsertedStart":true}'><td>x</td></tr>
+</tbody></table>
+
+<p>a</p>
+
+<p>b</p>
+
+<p>c</p>
+!! end
+
+!! test
+Paragraph wrapping suppressed in html p
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/php+tidy
+<p>
+
+
+hi
+
+
+
+</p>
+!! html/parsoid
+<p data-parsoid='{"stx":"html"}'>
+
+
+hi
+
+
+
+</p>
+!! end
+
+!! test
+Dangling table row doesn't prevent p-wrapping
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+{|
+| hi
+|-
+|} ho
+!! html/parsoid
+<table>
+<tbody><tr><td>hi</td></tr>
+<tr class="mw-empty-elt"></tr>
+</tbody></table><p> ho</p>
+!! end
+
###
### Preformatted text
###
</p>
</blockquote>
+!! html+tidy
+<blockquote>
+<p>Foo <del>bar</del> <ins>baz</ins> quux
+</p>
+</blockquote>
!! end
!! test
</blockquote>
!! html+tidy
-<blockquote><p>Foo </p><del>bar</del> <ins>baz</ins><p> quux
+<blockquote><p>Foo <del>bar</del> <ins>baz</ins> quux
</p></blockquote>
!! end
<pre class="one two">hi</pre>
!! html/parsoid
-<pre typeof="mw:Extension/pre" about="#mwt2" class="one two" data-mw='{"name":"pre","attrs":{"class":"one two"},"body":{"extsrc":"hi"}}'>hi</pre>
+<pre class="one two" typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{"class":"one two"},"body":{"extsrc":"hi"}}'>hi</pre>
!! end
!! test
</p>
!! end
+## Remex doesn't account for fostered content.
+## The difference between Parsoid and the PHP parser can be attributed to core
+## commit 674e8388cba and 710618f89af in Parsoid's repo. Parsoid doesn't
+## tokenize unmatched extension tags that shadow html tags as strings to ease
+## an escaping mechanism. See the comment in `maybeExtensionTag`.
!! test
Handle broken pre-like tags (T66025)
!! options
<pre>x</pre>
<pre <table></table>
!! html/parsoid
-<pre about="#mwt1" typeof="mw:Transclusion mw:Extension/pre" data-parsoid='{"a":{"<pre":null},"sa":{"<pre":""},"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<pre <pre>x</pre>"}},"i":0}}]}'>x</pre>
+<pre typeof="mw:Extension/pre mw:Transclusion" about="#mwt2" data-parsoid='{"stx":"html","a":{"<pre":null},"sa":{"<pre":""},"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<pre <pre>x</pre>"}},"i":0}}]}'>x</pre>
+
+<pre data-parsoid='{"stx":"html","src":"<pre </table>","tagWidths":[13,0],"a":{"<":null,"table":null},"sa":{"<":"","table":""},"fostered":true,"autoInsertedEnd":true}'></pre><table data-parsoid='{"stx":"html","autoInsertedEnd":true}'></table>
+!! end
+## Similar to the above, but shows the difference between extension and html tags
+!! test
+Less than in attribute position
+!! wikitext
+<pre <pre>123</pre>
-<p><pre </p>
+<div <div>123</div>
+!! html/php+tidy
+<pre>123</pre><p>
+<div </p><div>123</div>
+!! html/parsoid
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{"<pre":""},"body":{"extsrc":"123"}}'>123</pre><p>
-<table></table>
+<div </p><div>123</div>
!! end
!! test
<pre typeof="mw:Extension/pre" about="#mwt2" style="width:50%;" data-mw='{"name":"pre","attrs":{"style":"width:50%;"},"body":{"extsrc":"{{echo|foo}}"}}'>{{echo|foo}}</pre>
!! end
-# TODO / maybe: fix wt2wt for this
-!! test
-Parsoid: Don't paragraph-wrap fosterable content
-!! options
-parsoid=wt2html
-!! wikitext
-{|
-<td></td>
-<td></td>
-
-
-
-|}
-!! html
-<table>
-
-<tbody>
-<tr>
-<td></td>
-
-<td></td></tr>
-
-
-
-</tbody></table>
-!! end
-
!! test
Self-closed pre
!! wikitext
<pre></pre>
!! html/parsoid
-<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":null}'></pre>
+<pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{}}'></pre>
!! end
!! test
-Parsoid: Don't paragraph-wrap fosterable content even if table syntax is unbalanced
-!! options
-parsoid=wt2html
+Newline before table-close generates empty table row: T208619
!! wikitext
{|
-<td>
-<td>
-</td>
-
-
|}
-!! html
+!! 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
+parsoid=wt2html
+!! wikitext
+{|
+<td>
+<td>
+</td>
+
+
+
+|}
+!! html/php+tidy
+<table>
+<tbody><tr><td>
+</td><td>
+</td>
+
+
+
+</tr><tr><td></td></tr></tbody></table>
+!! html/parsoid
<table>
<tbody>
</p><p>b
</p><p>c
</p>
-<ul><li> d</li></ul>
+<ul><li>d</li></ul>
!! end
e}}
{{echo|
-* f}}
+*f}}
{{echo|
}}g
</pre>
<p><br />
</p>
-<ul><li> f</li></ul>
+<ul><li>f</li></ul>
<p><br />
</p>
<pre>g
!! 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&action=edit">bar</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:ExtLink" class="external text" href="http://example.org/index.php?title=Parser_test&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
2c. Indent-Pre and tables (T44252)
!! wikitext
{|
- |+ foo
- ! | bar
+ |+foo
+ ! |bar
|}
!! html
<table>
-<caption> foo
+<caption>foo
</caption>
<tr>
-<th> bar
+<th>bar
</th></tr></table>
!!end
!! wikitext
a
{|
- | b
+ |b
|}
!! html/php
<pre>a
</pre>
<table>
<tr>
-<td> b
+<td>b
</td></tr></table>
!! html/parsoid
!! end
-!!test
+!! test
+2h. Indent pre in tables
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+{|
+ !
+ foo
+ !
+ bar
+ |-
+ |
+ baz
+ {{!}}
+ bam
+ |}
+!! html/php
+<table>
+<tr>
+<th>
+<pre>foo
+</pre>
+</th>
+<th>
+<pre>bar
+</pre>
+</th></tr>
+<tr>
+<td>
+<pre>baz
+</pre>
+</td>
+<td>
+<pre>bam
+</pre>
+</td></tr></table>
+
+!! html/parsoid
+<table>
+ <tbody><tr><th>
+<pre>foo</pre>
+</th><th>
+<pre>bar</pre>
+</th></tr><tr>
+ <td>
+<pre>baz</pre>
+</td><td data-parsoid='{"startTagSrc":"{{!}}"}'>
+<pre>bam</pre>
+</td></tr></tbody></table>
+!! end
+
+!! test
3a. Indent-Pre and block tags (single-line html)
!! wikitext
a <p> foo </p>
c <blockquote> foo </blockquote>
<pre><span> foo </span>
</pre>
-!! html/parsoid
- <p>a </p><p data-parsoid='{"stx":"html"}'> foo </p>
- <p>b </p><div data-parsoid='{"stx":"html"}'> foo </div>
- <p>c </p><blockquote data-parsoid='{"stx":"html"}'> foo </blockquote>
-<pre><span> foo </span>
-</pre>
!! html/php+tidy
<p> a </p><p> foo </p><p>
b </p><div> foo </div><p>
c </p><blockquote><p> foo </p></blockquote>
<pre><span> foo </span>
</pre>
+!! html/parsoid
+<p> a </p><p data-parsoid='{"stx":"html"}'> foo </p><p>
+ b </p><div data-parsoid='{"stx":"html"}'> foo </div><p>
+ c </p><blockquote data-parsoid='{"stx":"html"}'><p> foo </p></blockquote>
+<pre><span data-parsoid='{"stx":"html"}'> foo </span></pre>
!! end
-!!test
+!! test
3b. Indent-Pre and block tags (multi-line html)
!! wikitext
a <span>foo</span>
- b <div> foo </div>
-!! html
+<!-- comment --> b <div> foo </div>
+!! html/php
<pre>a <span>foo</span>
</pre>
b <div> foo </div>
!! html/parsoid
<pre>a <span data-parsoid='{"stx":"html"}'>foo</span></pre>
- b <div data-parsoid='{"stx":"html"}'> foo </div>
+<!-- comment --> <p>b </p><div data-parsoid='{"stx":"html"}'> foo </div>
!! html/php+tidy
<pre>a <span>foo</span>
</pre><p>
b </p><div> foo </div>
-!!end
+!! end
!!test
3c. Indent-Pre and block tags (pre-content on separate line)
!! test
4. Indent-Pre and extension tags
+!! options
+parsoid=wt2html,html2html
!! wikitext
a <tag />
-!! html/php
- a <pre>
-NULL
+!! html/php+tidy
+<p> a </p><pre>NULL
array (
)
</pre>
-
!! html/parsoid
- a <pre typeof="mw:Extension/tag" about="#mwt2" data-parsoid='{}' data-mw='{"name":"tag","attrs":{},"body":null}'></pre>
+<p> a </p><pre typeof="mw:Extension/tag" about="#mwt2" data-mw='{"name":"tag","attrs":{}}'></pre>
!! end
!! test
<pre class="123">hi</pre>
!! html/parsoid
- <pre typeof="mw:Extension/pre" about="#mwt2" class="123" data-mw='{"name":"pre","attrs":{"class":"123"},"body":{"extsrc":"hi"}}'>hi</pre>
+ <pre class="123" typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{"class":"123"},"body":{"extsrc":"hi"}}'>hi</pre>
!! end
!!test
!! test
Simple definition
!! wikitext
-; name : Definition
+;name :Definition
!! html
-<dl><dt> name </dt>
-<dd> Definition</dd></dl>
+<dl><dt>name</dt>
+<dd>Definition</dd></dl>
!! end
!! test
Definition list for indentation only
!! wikitext
-: Indented text
+:Indented text
!! html
-<dl><dd> Indented text</dd></dl>
+<dl><dd>Indented text</dd></dl>
!! end
!! test
Definition list with URL link
!! wikitext
-; http://example.com/ : definition
+;http://example.com/ :definition
!! html
-<dl><dt> <a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a> </dt>
-<dd> definition</dd></dl>
+<dl><dt><a rel="nofollow" class="external free" href="http://example.com/">http://example.com/</a></dt>
+<dd>definition</dd></dl>
!! end
!! test
Definition list with wikilink containing colon
!! wikitext
-; [[Help:FAQ]]: The least-read page on Wikipedia
+;[[Help:FAQ]]:The least-read page on Wikipedia
!! html
-<dl><dt> <a href="/index.php?title=Help:FAQ&action=edit&redlink=1" class="new" title="Help:FAQ (page does not exist)">Help:FAQ</a></dt>
-<dd> The least-read page on Wikipedia</dd></dl>
+<dl><dt><a href="/index.php?title=Help:FAQ&action=edit&redlink=1" class="new" title="Help:FAQ (page does not exist)">Help:FAQ</a></dt>
+<dd>The least-read page on Wikipedia</dd></dl>
!! end
!! test
Definition list with news link containing colon
!! wikitext
-; news:alt.wikipedia.rox: This isn't even a real newsgroup!
+;news:alt.wikipedia.rox :This isn't even a real newsgroup!
!! html/php
-<dl><dt> <a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a></dt>
-<dd> This isn't even a real newsgroup!</dd></dl>
+<dl><dt><a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a></dt>
+<dd>This isn't even a real newsgroup!</dd></dl>
!! html/parsoid
-<dl><dt> <a rel="mw:ExtLink" class="external free" href="news:alt.wikipedia.rox" data-parsoid='{"stx":"url"}'>news:alt.wikipedia.rox</a></dt><dd data-parsoid='{"stx":"row"}'> This isn't even a real newsgroup!</dd></dl>
+<dl><dt><a rel="mw:ExtLink" class="external free" href="news:alt.wikipedia.rox" data-parsoid='{"stx":"url"}'>news:alt.wikipedia.rox</a></dt><dd data-parsoid='{"stx":"row"}'>This isn't even a real newsgroup!</dd></dl>
!! end
!! test
Malformed definition list with colon
!! wikitext
-; news:alt.wikipedia.rox -- don't crash or enter an infinite loop
+;news:alt.wikipedia.rox -- don't crash or enter an infinite loop
!! html
-<dl><dt> <a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a> -- don't crash or enter an infinite loop</dt></dl>
+<dl><dt><a rel="nofollow" class="external free" href="news:alt.wikipedia.rox">news:alt.wikipedia.rox</a> -- don't crash or enter an infinite loop</dt></dl>
!! end
!! test
Definition lists: colon in external link text
!! wikitext
-; [http://www.wikipedia2.org/ Wikipedia : The Next Generation]: OK, I made that up
+;[http://www.wikipedia2.org/ Wikipedia :The Next Generation] :OK, I made that up
!! html
-<dl><dt> <a rel="nofollow" class="external text" href="http://www.wikipedia2.org/">Wikipedia : The Next Generation</a></dt>
-<dd> OK, I made that up</dd></dl>
+<dl><dt><a rel="nofollow" class="external text" href="http://www.wikipedia2.org/">Wikipedia :The Next Generation</a></dt>
+<dd>OK, I made that up</dd></dl>
!! end
!! test
Definition lists: self-closed tag
!! wikitext
-;one<br/>two : two-line fun
+;one<br/>two :two-line fun
!! html
-<dl><dt>one<br />two </dt>
-<dd> two-line fun</dd></dl>
+<dl><dt>one<br />two</dt>
+<dd>two-line fun</dd></dl>
!! end
!! test
Definition lists: ignore colons inside tags
!! wikitext
-;one <b>two : tag <i>fun:</i>:</b>: def
+;one <b>two : tag <i>fun:</i>:</b>:def
!! html
<dl><dt>one <b>two : tag <i>fun:</i>:</b></dt>
-<dd> def</dd></dl>
+<dd>def</dd></dl>
!! end
!! test
Definition lists: excess closed tags
!! wikitext
-;one</b>two : bad tag fun
+;one</b>two :bad tag fun
!! html/php+tidy
-<dl><dt>onetwo </dt>
-<dd> bad tag fun</dd></dl>
+<dl><dt>onetwo</dt>
+<dd>bad tag fun</dd></dl>
!! html/parsoid
<dl>
<dt>onetwo</dt>
Definition and unordered list using wiki syntax nested in unordered list using html tags.
!! wikitext
<ul><li>
-; term : description
-* unordered
+;term :description
+*unordered
</li></ul>
!! html
<ul><li>
-<dl><dt> term </dt>
-<dd> description</dd></dl>
-<ul><li> unordered</li></ul>
+<dl><dt>term</dt>
+<dd>description</dd></dl>
+<ul><li>unordered</li></ul>
</li></ul>
!! end
!! test
Definition list with empty definition and following paragraph
!! wikitext
-; term:
+;term:
+
Paragraph text
!! html
-<dl><dt> term</dt>
+<dl><dt>term</dt>
<dd></dd></dl>
<p>Paragraph text
</p>
</p>
!! end
+!! test
+Definition Lists: Hacky use to indent tables (with content following table)
+!! wikitext
+:{|
+|foo
+|bar
+|} <!--c1--> this text should be part of the dl
+!! html/php+tidy
+<dl><dd><table>
+<tbody><tr>
+<td>foo
+</td>
+<td>bar
+</td></tr></tbody></table> this text should be part of the dl</dd></dl>
+!! html/parsoid
+<dl><dd><table>
+<tbody><tr>
+<td>foo
+</td>
+<td>bar
+</td></tr></tbody></table> <!--c1--> this text should be part of the dl</dd></dl>
+!! end
+
!! test
Definition Lists: Hacky use to indent tables, with comments (T65979)
!! wikitext
!! test
Definition Lists: Hacky use to indent tables, with comment before table
+!!options
+parsoid=wt2html
!! wikitext
::<!-- foo -->{|
|foo
!! test
Definition Lists: Hacky use to indent tables (WS-insensitive)
!! wikitext
-: {|
+:{|
|a
|}
!! html/php
</td></tr></table></dd></dl>
!! html/parsoid
-<dl><dd> <table>
+<dl><dd><table>
<tbody><tr><td>a</td></tr>
-</tbody></table> </dd></dl>
+</tbody></table></dd></dl>
!! end
## The PHP parser treats : items (dd) without a corresponding ; item (dt)
!! wikitext
:{|
|-
-| a
-* b
+|a
+
+*b
|-
-| c
-* d
+|c
+
+*d
|}
!! html
<dl><dd><table>
<tr>
-<td> a
-<ul><li> b</li></ul>
+<td>a
+<ul><li>b</li></ul>
</td></tr>
<tr>
-<td> c
-<ul><li> d</li></ul>
+<td>c
+<ul><li>d</li></ul>
</td></tr></table></dd></dl>
!! end
!! test
Definition Lists: Mixed Lists: Test 1
!! wikitext
-:;* foo
-::* bar
-:; baz
+:;*foo
+::*bar
+:;baz
!! html/php
-<dl><dd><dl><dt><ul><li> foo</li>
-<li> bar</li></ul></dt></dl>
-<dl><dt> baz</dt></dl></dd></dl>
+<dl><dd><dl><dt><ul><li>foo</li>
+<li>bar</li></ul></dt></dl>
+<dl><dt>baz</dt></dl></dd></dl>
!! html/php+tidy
-<dl><dd><dl><dt><ul><li> foo</li>
-<li> bar</li></ul></dt></dl>
-<dl><dt> baz</dt></dl></dd></dl>
+<dl><dd><dl><dt><ul><li>foo</li>
+<li>bar</li></ul></dt></dl>
+<dl><dt>baz</dt></dl></dd></dl>
!! html/parsoid
<dl>
<dd><dl>
<dt><ul>
-<li> foo
+<li>foo
</li>
</ul></dt>
<dd><ul>
-<li> bar
+<li>bar
</li>
</ul></dd>
-<dt> baz</dt>
+<dt>baz</dt>
</dl></dd>
</dl>
!! end
!! test
Definition Lists: Mixed Lists: Test 2
!! wikitext
-*: d1
-*: d2
+*:d1
+*:d2
!! html
-<ul><li><dl><dd> d1</dd>
-<dd> d2</dd></dl></li></ul>
+<ul><li><dl><dd>d1</dd>
+<dd>d2</dd></dl></li></ul>
!! end
!! test
Definition Lists: Mixed Lists: Test 3
!! wikitext
-*::: d1
-*::: d2
+*:::d1
+*:::d2
!! html
-<ul><li><dl><dd><dl><dd><dl><dd> d1</dd>
-<dd> d2</dd></dl></dd></dl></dd></dl></li></ul>
+<ul><li><dl><dd><dl><dd><dl><dd>d1</dd>
+<dd>d2</dd></dl></dd></dl></dd></dl></li></ul>
!! end
*;d1 :d2
*;d3 :d4
!! html
-<ul><li><dl><dt>d1 </dt>
+<ul><li><dl><dt>d1</dt>
<dd>d2</dd>
-<dt>d3 </dt>
+<dt>d3</dt>
<dd>d4</dd></dl></li></ul>
!! end
Definition Lists: Mixed Lists: Test 5
!! wikitext
*:d1
-*:: d2
+*::d2
!! html
<ul><li><dl><dd>d1
-<dl><dd> d2</dd></dl></dd></dl></li></ul>
+<dl><dd>d2</dd></dl></dd></dl></li></ul>
!! end
Definition Lists: Mixed Lists: Test 6
!! wikitext
#*:d1
-#*::: d3
+#*:::d3
!! html
<ol><li><ul><li><dl><dd>d1
-<dl><dd><dl><dd> d3</dd></dl></dd></dl></dd></dl></li></ul></li></ol>
+<dl><dd><dl><dd>d3</dd></dl></dd></dl></dd></dl></li></ul></li></ol>
!! end
!! test
Definition Lists: Mixed Lists: Test 7
!! wikitext
-:* d1
-:* d2
+:*d1
+:*d2
!! html
-<dl><dd><ul><li> d1</li>
-<li> d2</li></ul></dd></dl>
+<dl><dd><ul><li>d1</li>
+<li>d2</li></ul></dd></dl>
!! end
!! test
Definition Lists: Mixed Lists: Test 8
!! wikitext
-:* d1
-::* d2
+:*d1
+::*d2
!! html
-<dl><dd><ul><li> d1</li></ul>
-<dl><dd><ul><li> d2</li></ul></dd></dl></dd></dl>
+<dl><dd><ul><li>d1</li></ul>
+<dl><dd><ul><li>d2</li></ul></dd></dl></dd></dl>
!! end
!! wikitext
*;foo :bar
!! html
-<ul><li><dl><dt>foo </dt>
+<ul><li><dl><dt>foo</dt>
<dd>bar</dd></dl></li></ul>
!! end
!! wikitext
*#;foo :bar
!! html
-<ul><li><ol><li><dl><dt>foo </dt>
+<ul><li><ol><li><dl><dt>foo</dt>
<dd>bar</dd></dl></li></ol></li></ul>
!! end
*#*#;*;;foo :bar
*#*#;boo :baz
!! html/php
-<ul><li><ol><li><ul><li><ol><li><dl><dt>foo </dt>
+<ul><li><ol><li><ul><li><ol><li><dl><dt>foo</dt>
<dd><ul><li><dl><dt><dl><dt>bar</dt></dl></dd></dl></li></ul></dd></dl>
-<dl><dt>boo </dt>
+<dl><dt>boo</dt>
<dd>baz</dd></dl></li></ol></li></ul></li></ol></li></ul>
!! html/php+tidy
-<ul><li><ol><li><ul><li><ol><li><dl><dt>foo </dt>
+<ul><li><ol><li><ul><li><ol><li><dl><dt>foo</dt>
<dd><ul><li><dl><dt><dl><dt>bar</dt></dl></dt></dl></li></ul></dd></dl></li></ol></li></ul>
-<dl><dt>boo </dt>
+<dl><dt>boo</dt>
<dd>baz</dd></dl></li></ol></li></ul>
!! html/parsoid
<ul>
<dl>
<dt>
<dl>
-<dt>foo<span typeof="mw:Placeholder" data-parsoid='{"src":" "}'> </span></dt>
+<dt>foo</dt>
<dd data-parsoid='{"stx":"row"}'>bar</dd>
</dl></dt>
</dl></li>
</ul></dt>
-<dt>boo<span typeof="mw:Placeholder" data-parsoid='{"src":" "}'> </span></dt>
+<dt>boo</dt>
<dd data-parsoid='{"stx":"row"}'>baz</dd>
</dl></li>
</ol></li>
</ul>
!! end
+!! test
+Definition Lists: Mixed Lists: Test 13
+!! wikitext
+*#*#;*;;foo : bar
+*#*#;boo : baz
+!! html+tidy
+<ul><li><ol><li><ul><li><ol><li><dl><dt>foo </dt>
+<dd><ul><li><dl><dt><dl><dt>bar</dt></dl></dt></dl></li></ul></dd></dl></li></ol></li></ul>
+<dl><dt>boo </dt>
+<dd>baz</dd></dl></li></ol></li></ul>
+!! end
+
# FIXME: Maybe get rid of this test?
# From whitelist:
# * The test is wrong, there are two colons where there should be :;
!! test
Definition Lists: Weird Ones: Test 1
!! wikitext
-*#;*::;; foo : bar (who uses this?)
+*#;*::;;foo :bar (who uses this?)
!! html/php+tidy
-<ul><li><ol><li><dl><dt> foo </dt>
-<dd><ul><li><dl><dd><dl><dd><dl><dt><dl><dt> bar (who uses this?)</dt></dl></dt></dl></dd></dl></dd></dl></li></ul></dd></dl></li></ol></li></ul>
+<ul><li><ol><li><dl><dt>foo</dt>
+<dd><ul><li><dl><dd><dl><dd><dl><dt><dl><dt>bar (who uses this?)</dt></dl></dt></dl></dd></dl></dd></dl></li></ul></dd></dl></li></ol></li></ul>
!! html/parsoid
<ul>
<li>
<dl>
<dt>
<dl>
-<dt> foo<span typeof="mw:DisplaySpace mw:Placeholder" data-parsoid='{"src":" ","isDisplayHack":true}'> </span></dt>
-<dd data-parsoid='{"stx":"row"}'> bar (who uses this?)</dd>
+<dt>foo</dt>
+<dd data-parsoid='{"stx":"row"}'>bar (who uses this?)</dd>
</dl></dt>
</dl></dd>
</dl></dd>
Definition Lists: colons and tables 1
!! wikitext
:{|
-| x
+|x
|}
:{|
-| y
+|y
|}
!! html/php
<dl><dd><table>
<tr>
-<td> x
+<td>x
</td></tr></table></dd></dl>
<dl><dd><table>
<tr>
-<td> y
+<td>y
</td></tr></table></dd></dl>
!! html/parsoid
<dl><dd><table>
<tr>
-<td> x
+<td>x
</td></tr></table></dd>
<dd><table>
<tr>
-<td> y
+<td>y
</td></tr></table></dd></dl>
!! end
!! wikitext
URL in text: [http://example.com http://example.com]
!! html/php
-<p>URL in text: <a rel="nofollow" class="external free" href="http://example.com">http://example.com</a>
+<p>URL in text: <a rel="nofollow" class="external text" href="http://example.com">http://example.com</a>
</p>
!! html/parsoid
-<p>URL in text: <a rel="mw:ExtLink" class="external free" href="http://example.com">http://example.com</a></p>
+<p>URL in text: <a rel="mw:ExtLink" class="external text" href="http://example.com">http://example.com</a></p>
!! end
!! test
http://[2404:130:0:1000::187:2]/index.php
Examples from RFC 2373, section 2.2:
-* http://[1080::8:800:200C:417A]/unicast
-* http://[FF01::101]/multicast
-* http://[::1]/loopback
-* http://[::]/unspecified
-* http://[::13.1.68.3]/ipv4compat
-* http://[::FFFF:129.144.52.38]/ipv4compat
+
+*http://[1080::8:800:200C:417A]/unicast
+*http://[FF01::101]/multicast
+*http://[::1]/loopback
+*http://[::]/unspecified
+*http://[::13.1.68.3]/ipv4compat
+*http://[::FFFF:129.144.52.38]/ipv4compat
Examples from RFC 2732, section 2:
-* http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
-* http://[1080:0:0:0:8:800:200C:417A]/index.html
-* http://[3ffe:2a00:100:7031::1]
-* http://[1080::8:800:200C:417A]/foo
-* http://[::192.9.5.5]/ipng
-* http://[::FFFF:129.144.52.38]:80/index.html
-* http://[2010:836B:4179::836B:4179]
+*http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
+*http://[1080:0:0:0:8:800:200C:417A]/index.html
+*http://[3ffe:2a00:100:7031::1]
+*http://[1080::8:800:200C:417A]/foo
+*http://[::192.9.5.5]/ipng
+*http://[::FFFF:129.144.52.38]:80/index.html
+*http://[2010:836B:4179::836B:4179]
!! html/php
<p><a rel="nofollow" class="external free" href="http://[2404:130:0:1000::187:2]/index.php">http://[2404:130:0:1000::187:2]/index.php</a>
</p><p>Examples from <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc2373">RFC 2373</a>, section 2.2:
</p>
-<ul><li> <a rel="nofollow" class="external free" href="http://[1080::8:800:200C:417A]/unicast">http://[1080::8:800:200C:417A]/unicast</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[FF01::101]/multicast">http://[FF01::101]/multicast</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::1]/loopback">http://[::1]/loopback</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::]/unspecified">http://[::]/unspecified</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::13.1.68.3]/ipv4compat">http://[::13.1.68.3]/ipv4compat</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::FFFF:129.144.52.38]/ipv4compat">http://[::FFFF:129.144.52.38]/ipv4compat</a></li></ul>
+<ul><li><a rel="nofollow" class="external free" href="http://[1080::8:800:200C:417A]/unicast">http://[1080::8:800:200C:417A]/unicast</a></li>
+<li><a rel="nofollow" class="external free" href="http://[FF01::101]/multicast">http://[FF01::101]/multicast</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::1]/loopback">http://[::1]/loopback</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::]/unspecified">http://[::]/unspecified</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::13.1.68.3]/ipv4compat">http://[::13.1.68.3]/ipv4compat</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::FFFF:129.144.52.38]/ipv4compat">http://[::FFFF:129.144.52.38]/ipv4compat</a></li></ul>
<p>Examples from <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc2732">RFC 2732</a>, section 2:
</p>
-<ul><li> <a rel="nofollow" class="external free" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">http://[1080:0:0:0:8:800:200C:417A]/index.html</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[3ffe:2a00:100:7031::1]">http://[3ffe:2a00:100:7031::1]</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[1080::8:800:200C:417A]/foo">http://[1080::8:800:200C:417A]/foo</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::192.9.5.5]/ipng">http://[::192.9.5.5]/ipng</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[::FFFF:129.144.52.38]:80/index.html">http://[::FFFF:129.144.52.38]:80/index.html</a></li>
-<li> <a rel="nofollow" class="external free" href="http://[2010:836B:4179::836B:4179]">http://[2010:836B:4179::836B:4179]</a></li></ul>
+<ul><li><a rel="nofollow" class="external free" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html</a></li>
+<li><a rel="nofollow" class="external free" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">http://[1080:0:0:0:8:800:200C:417A]/index.html</a></li>
+<li><a rel="nofollow" class="external free" href="http://[3ffe:2a00:100:7031::1]">http://[3ffe:2a00:100:7031::1]</a></li>
+<li><a rel="nofollow" class="external free" href="http://[1080::8:800:200C:417A]/foo">http://[1080::8:800:200C:417A]/foo</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::192.9.5.5]/ipng">http://[::192.9.5.5]/ipng</a></li>
+<li><a rel="nofollow" class="external free" href="http://[::FFFF:129.144.52.38]:80/index.html">http://[::FFFF:129.144.52.38]:80/index.html</a></li>
+<li><a rel="nofollow" class="external free" href="http://[2010:836B:4179::836B:4179]">http://[2010:836B:4179::836B:4179]</a></li></ul>
!! html/parsoid
<p><a rel="mw:ExtLink" class="external free" href="http://[2404:130:0:1000::187:2]/index.php">http://[2404:130:0:1000::187:2]/index.php</a></p>
-<p>Examples from <a href="https://tools.ietf.org/html/rfc2373" rel="mw:ExtLink" class="external text">RFC 2373</a>, section 2.2:</p>
-<ul><li> <a rel="mw:ExtLink" class="external free" href="http://[1080::8:800:200C:417A]/unicast">http://[1080::8:800:200C:417A]/unicast</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[FF01::101]/multicast">http://[FF01::101]/multicast</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::1]/loopback">http://[::1]/loopback</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::]/unspecified">http://[::]/unspecified</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::13.1.68.3]/ipv4compat">http://[::13.1.68.3]/ipv4compat</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::FFFF:129.144.52.38]/ipv4compat">http://[::FFFF:129.144.52.38]/ipv4compat</a></li></ul>
+<p>Examples from <a href="https://tools.ietf.org/html/rfc2373" rel="mw:ExtLink" class="external mw-magiclink">RFC 2373</a>, section 2.2:</p>
+<ul><li><a rel="mw:ExtLink" class="external free" href="http://[1080::8:800:200C:417A]/unicast">http://[1080::8:800:200C:417A]/unicast</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[FF01::101]/multicast">http://[FF01::101]/multicast</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::1]/loopback">http://[::1]/loopback</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::]/unspecified">http://[::]/unspecified</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::13.1.68.3]/ipv4compat">http://[::13.1.68.3]/ipv4compat</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::FFFF:129.144.52.38]/ipv4compat">http://[::FFFF:129.144.52.38]/ipv4compat</a></li></ul>
-<p>Examples from <a href="https://tools.ietf.org/html/rfc2732" rel="mw:ExtLink" class="external text">RFC 2732</a>, section 2:</p>
-<ul><li> <a rel="mw:ExtLink" class="external free" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">http://[1080:0:0:0:8:800:200C:417A]/index.html</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[3ffe:2a00:100:7031::1]">http://[3ffe:2a00:100:7031::1]</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[1080::8:800:200C:417A]/foo">http://[1080::8:800:200C:417A]/foo</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::192.9.5.5]/ipng">http://[::192.9.5.5]/ipng</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[::FFFF:129.144.52.38]:80/index.html">http://[::FFFF:129.144.52.38]:80/index.html</a></li>
-<li> <a rel="mw:ExtLink" class="external free" href="http://[2010:836B:4179::836B:4179]">http://[2010:836B:4179::836B:4179]</a></li></ul>
+<p>Examples from <a href="https://tools.ietf.org/html/rfc2732" rel="mw:ExtLink" class="external mw-magiclink">RFC 2732</a>, section 2:</p>
+<ul><li><a rel="mw:ExtLink" class="external free" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">http://[1080:0:0:0:8:800:200C:417A]/index.html</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[3ffe:2a00:100:7031::1]">http://[3ffe:2a00:100:7031::1]</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[1080::8:800:200C:417A]/foo">http://[1080::8:800:200C:417A]/foo</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::192.9.5.5]/ipng">http://[::192.9.5.5]/ipng</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[::FFFF:129.144.52.38]:80/index.html">http://[::FFFF:129.144.52.38]:80/index.html</a></li>
+<li><a rel="mw:ExtLink" class="external free" href="http://[2010:836B:4179::836B:4179]">http://[2010:836B:4179::836B:4179]</a></li></ul>
!! end
!! test
[http://[2404:130:0:1000::187:2]/index.php test]
Examples from RFC 2373, section 2.2:
-* [http://[1080::8:800:200C:417A] unicast]
-* [http://[FF01::101] multicast]
-* [http://[::1]/ loopback]
-* [http://[::] unspecified]
-* [http://[::13.1.68.3] ipv4compat]
-* [http://[::FFFF:129.144.52.38] ipv4compat]
+
+*[http://[1080::8:800:200C:417A] unicast]
+*[http://[FF01::101] multicast]
+*[http://[::1]/ loopback]
+*[http://[::] unspecified]
+*[http://[::13.1.68.3] ipv4compat]
+*[http://[::FFFF:129.144.52.38] ipv4compat]
Examples from RFC 2732, section 2:
-* [http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html 1]
-* [http://[1080:0:0:0:8:800:200C:417A]/index.html 2]
-* [http://[3ffe:2a00:100:7031::1] 3]
-* [http://[1080::8:800:200C:417A]/foo 4]
-* [http://[::192.9.5.5]/ipng 5]
-* [http://[::FFFF:129.144.52.38]:80/index.html 6]
-* [http://[2010:836B:4179::836B:4179] 7]
+*[http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html 1]
+*[http://[1080:0:0:0:8:800:200C:417A]/index.html 2]
+*[http://[3ffe:2a00:100:7031::1] 3]
+*[http://[1080::8:800:200C:417A]/foo 4]
+*[http://[::192.9.5.5]/ipng 5]
+*[http://[::FFFF:129.144.52.38]:80/index.html 6]
+*[http://[2010:836B:4179::836B:4179] 7]
!! html/php
<p><a rel="nofollow" class="external text" href="http://[2404:130:0:1000::187:2]/index.php">test</a>
</p><p>Examples from <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc2373">RFC 2373</a>, section 2.2:
</p>
-<ul><li> <a rel="nofollow" class="external text" href="http://[1080::8:800:200C:417A]">unicast</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[FF01::101]">multicast</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::1]/">loopback</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::]">unspecified</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::13.1.68.3]">ipv4compat</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::FFFF:129.144.52.38]">ipv4compat</a></li></ul>
+<ul><li><a rel="nofollow" class="external text" href="http://[1080::8:800:200C:417A]">unicast</a></li>
+<li><a rel="nofollow" class="external text" href="http://[FF01::101]">multicast</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::1]/">loopback</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::]">unspecified</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::13.1.68.3]">ipv4compat</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::FFFF:129.144.52.38]">ipv4compat</a></li></ul>
<p>Examples from <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc2732">RFC 2732</a>, section 2:
</p>
-<ul><li> <a rel="nofollow" class="external text" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">1</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">2</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[3ffe:2a00:100:7031::1]">3</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[1080::8:800:200C:417A]/foo">4</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::192.9.5.5]/ipng">5</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[::FFFF:129.144.52.38]:80/index.html">6</a></li>
-<li> <a rel="nofollow" class="external text" href="http://[2010:836B:4179::836B:4179]">7</a></li></ul>
+<ul><li><a rel="nofollow" class="external text" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">1</a></li>
+<li><a rel="nofollow" class="external text" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">2</a></li>
+<li><a rel="nofollow" class="external text" href="http://[3ffe:2a00:100:7031::1]">3</a></li>
+<li><a rel="nofollow" class="external text" href="http://[1080::8:800:200C:417A]/foo">4</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::192.9.5.5]/ipng">5</a></li>
+<li><a rel="nofollow" class="external text" href="http://[::FFFF:129.144.52.38]:80/index.html">6</a></li>
+<li><a rel="nofollow" class="external text" href="http://[2010:836B:4179::836B:4179]">7</a></li></ul>
!! html/parsoid
<p><a rel="mw:ExtLink" class="external text" href="http://[2404:130:0:1000::187:2]/index.php">test</a></p>
-<p>Examples from <a href="https://tools.ietf.org/html/rfc2373" rel="mw:ExtLink" class="external text">RFC 2373</a>, section 2.2:</p>
-<ul><li> <a rel="mw:ExtLink" class="external text" href="http://[1080::8:800:200C:417A]">unicast</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[FF01::101]">multicast</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::1]/">loopback</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::]">unspecified</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::13.1.68.3]">ipv4compat</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::FFFF:129.144.52.38]">ipv4compat</a></li></ul>
+<p>Examples from <a href="https://tools.ietf.org/html/rfc2373" rel="mw:ExtLink" class="external mw-magiclink">RFC 2373</a>, section 2.2:</p>
+<ul><li><a rel="mw:ExtLink" class="external text" href="http://[1080::8:800:200C:417A]">unicast</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[FF01::101]">multicast</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::1]/">loopback</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::]">unspecified</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::13.1.68.3]">ipv4compat</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::FFFF:129.144.52.38]">ipv4compat</a></li></ul>
-<p>Examples from <a href="https://tools.ietf.org/html/rfc2732" rel="mw:ExtLink" class="external text">RFC 2732</a>, section 2:</p>
-<ul><li> <a rel="mw:ExtLink" class="external text" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">1</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">2</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[3ffe:2a00:100:7031::1]">3</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[1080::8:800:200C:417A]/foo">4</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::192.9.5.5]/ipng">5</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[::FFFF:129.144.52.38]:80/index.html">6</a></li>
-<li> <a rel="mw:ExtLink" class="external text" href="http://[2010:836B:4179::836B:4179]">7</a></li></ul>
+<p>Examples from <a href="https://tools.ietf.org/html/rfc2732" rel="mw:ExtLink" class="external mw-magiclink">RFC 2732</a>, section 2:</p>
+<ul><li><a rel="mw:ExtLink" class="external text" href="http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html">1</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[1080:0:0:0:8:800:200C:417A]/index.html">2</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[3ffe:2a00:100:7031::1]">3</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[1080::8:800:200C:417A]/foo">4</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::192.9.5.5]/ipng">5</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[::FFFF:129.144.52.38]:80/index.html">6</a></li>
+<li><a rel="mw:ExtLink" class="external text" href="http://[2010:836B:4179::836B:4179]">7</a></li></ul>
!! end
!! test
</p>
!! end
+!! test
+Quotes wrapping HTML table
+!! wikitext
+'''<table><tr><td>hi</td></tr></table>'''
+!! html/php+tidy
+<b><table><tbody><tr><td>hi</td></tr></tbody></table></b>
+!! html/parsoid
+<b><table data-parsoid='{"stx":"html"}'><tbody><tr data-parsoid='{"stx":"html"}'><td data-parsoid='{"stx":"html"}'>hi</td></tr></tbody></table></b>
+!! end
# Parsoid inserts an empty bold tag pair at the end of the line, that the PHP
# parser strips. The wikitext contains just the first half of the bold
!! 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
{|style="color: red;" |} id="foo"
|foo
|}
-!! html
+!! html/php+tidy
+<table style=""color:">
+
+</table><table style="color: red;">
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+<table style=""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;">
A table with nothing but a caption
!! wikitext
{|
-|+ caption
+|+caption
|}
!! html/php
<table>
-<caption> caption
+<caption>caption
</caption><tr><td></td></tr></table>
!! html/parsoid
-<table><caption> caption</caption></table>
+<table><caption>caption</caption></table>
!! end
!! test
A table with caption with default-spaced attributes and a table row
!! wikitext
{|
-|+ style="color: red;" | caption1
+|+ style="color: red;" |caption1
|-
-| foo
+|foo
|}
!! html
<table>
-<caption style="color: red;"> caption1
+<caption style="color: red;">caption1
</caption>
<tr>
-<td> foo
+<td>foo
</td></tr></table>
!! end
!! wikitext
{|
|+style="color: red;"|caption2
-|+ style="color: red;"| caption3
+|+ style="color: red;"|caption3
|-
-| foo
+|foo
|}
!! html
<table>
<caption style="color: red;">caption2
</caption>
-<caption style="color: red;"> caption3
+<caption style="color: red;">caption3
</caption>
<tr>
-<td> foo
+<td>foo
</td></tr></table>
!! end
Table td-cell syntax variations
!! wikitext
{|
-| foo bar foo | baz
-| foo bar foo || baz
-| style='color:red;' | baz
-| style='color:red;' || baz
+|foo bar foo|baz
+|foo bar foo||baz
+|style='color:red;'|baz
+|style='color:red;'||baz
|}
!! html
<table>
<tr>
-<td> baz
+<td>baz
</td>
-<td> foo bar foo </td>
-<td> baz
+<td>foo bar foo</td>
+<td>baz
</td>
-<td style="color:red;"> baz
+<td style="color:red;">baz
</td>
-<td> style='color:red;' </td>
-<td> baz
+<td>style='color:red;'</td>
+<td>baz
</td></tr></table>
!! end
Simple table
!! wikitext
{|
-| 1 || 2
+|1||2
|-
-| 3 || 4
+|3||4
|}
!! html
<table>
<tr>
-<td> 1 </td>
-<td> 2
+<td>1</td>
+<td>2
</td></tr>
<tr>
-<td> 3 </td>
-<td> 4
+<td>3</td>
+<td>4
</td></tr></table>
!! end
Simple table but with multiple dashes for row wikitext
!! wikitext
{|
-| foo
+|foo
|-----
-| bar
+|bar
|}
!! html
<table>
<tr>
-<td> foo
+<td>foo
</td></tr>
<tr>
-<td> bar
+<td>bar
</td></tr></table>
!! end
{| border="1" cellpadding="2"
|+Multiplication table
|-
-! × !! 1 !! 2 !! 3
+!×!!1!!2!!3
|-
-! 1
-| 1 || 2 || 3
+!1
+|1||2||3
|-
-! 2
-| 2 || 4 || 6
+!2
+|2||4||6
|-
-! 3
-| 3 || 6 || 9
+!3
+|3||6||9
|-
-! 4
-| 4 || 8 || 12
+!4
+|4||8||12
|-
-! 5
-| 5 || 10 || 15
+!5
+|5||10||15
|}
!! html
<table border="1" cellpadding="2">
<caption>Multiplication table
</caption>
<tr>
-<th> × </th>
-<th> 1 </th>
-<th> 2 </th>
-<th> 3
+<th>×</th>
+<th>1</th>
+<th>2</th>
+<th>3
</th></tr>
<tr>
-<th> 1
+<th>1
</th>
-<td> 1 </td>
-<td> 2 </td>
-<td> 3
+<td>1</td>
+<td>2</td>
+<td>3
</td></tr>
<tr>
-<th> 2
+<th>2
</th>
-<td> 2 </td>
-<td> 4 </td>
-<td> 6
+<td>2</td>
+<td>4</td>
+<td>6
</td></tr>
<tr>
-<th> 3
+<th>3
</th>
-<td> 3 </td>
-<td> 6 </td>
-<td> 9
+<td>3</td>
+<td>6</td>
+<td>9
</td></tr>
<tr>
-<th> 4
+<th>4
</th>
-<td> 4 </td>
-<td> 8 </td>
-<td> 12
+<td>4</td>
+<td>8</td>
+<td>12
</td></tr>
<tr>
-<th> 5
+<th>5
</th>
-<td> 5 </td>
-<td> 10 </td>
-<td> 15
+<td>5</td>
+<td>10</td>
+<td>15
</td></tr></table>
!! end
Accept "||" in table headings
!! wikitext
{|
-!h1 || h2
+!h1||h2
|}
!! html
<table>
<tr>
-<th>h1 </th>
-<th> h2
+<th>h1</th>
+<th>h2
</th></tr></table>
!! end
Accept "!!" in table data
!! wikitext
{|
-| Foo!! ||
+|Foo!!||
|}
!! html
<table>
<tr>
-<td> Foo!! </td>
+<td>Foo!!</td>
<td>
</td></tr></table>
Accept "||" in indented table headings
!! wikitext
:{|
-!h1 || h2
+!h1||h2
|}
!! html
<dl><dd><table>
<tr>
-<th>h1 </th>
-<th> h2
+<th>h1</th>
+<th>h2
</th></tr></table></dd></dl>
!! end
Accept empty attributes in td/th cells (td/th cells starting with leading ||)
!! wikitext
{|
-!| h1
-|| a
+!|h1
+||a
|}
!! html
<table>
<tr>
-<th> h1
+<th>h1
</th>
-<td> a
+<td>a
</td></tr></table>
!! end
!! wikitext
{|
|-
-| !style="color:red" | bar
+|!style="color:red"|bar
|}
!! html
<table>
<tr>
-<td> bar
+<td>bar
</td></tr></table>
!!end
|style='color:red;'|+1
|style='color:blue;'|-1
|-
-| 1 || 2 || 3
-| 1 ||+2 ||-3
+|1||2||3
+|1||+2||-3
|-
| +1
| -1
<td style="color:blue;">-1
</td></tr>
<tr>
-<td> 1 </td>
-<td> 2 </td>
-<td> 3
+<td>1</td>
+<td>2</td>
+<td>3
</td>
-<td> 1 </td>
-<td>+2 </td>
+<td>1</td>
+<td>+2</td>
<td>-3
</td></tr>
<tr>
-<td> +1
+<td>+1
</td>
-<td> -1
+<td>-1
</td></tr></table>
!!end
Table rowspan
!! wikitext
{| border=1
-| Cell 1, row 1
-|rowspan=2| Cell 2, row 1 (and 2)
-| Cell 3, row 1
+|Cell 1, row 1
+|rowspan=2|Cell 2, row 1 (and 2)
+|Cell 3, row 1
|-
-| Cell 1, row 2
-| Cell 3, row 2
+|Cell 1, row 2
+|Cell 3, row 2
|}
!! html
<table border="1">
<tr>
-<td> Cell 1, row 1
+<td>Cell 1, row 1
</td>
-<td rowspan="2"> Cell 2, row 1 (and 2)
+<td rowspan="2">Cell 2, row 1 (and 2)
</td>
-<td> Cell 3, row 1
+<td>Cell 3, row 1
</td></tr>
<tr>
-<td> Cell 1, row 2
+<td>Cell 1, row 2
</td>
-<td> Cell 3, row 2
+<td>Cell 3, row 2
</td></tr></table>
!! end
!! html
<table border="1">
<tr>
-<td> α
+<td>α
</td>
<td>
<table bgcolor="#ABCDEF" border="2">
Table cell attributes: Pipes protected by nowikis should be treated as a plain character
!! wikitext
{|
-| title="foo" |bar
-| title="foo<nowiki>|</nowiki>" |bar
-| title="foo<nowiki>|</nowiki>" bar
+|title="foo" |bar
+|title="foo<nowiki>|</nowiki>" |bar
+|title="foo<nowiki>|</nowiki>" bar
|}
!! html/php
<table>
</td>
<td title="foo|">bar
</td>
-<td> title="foo|" bar
+<td>title="foo|" bar
</td></tr></table>
!! html/parsoid
Element attributes with double ! should not be broken up by <th>
!! wikitext
{|
-! hi <div class="!!">ha</div> ho
+!hi <div class="!!">ha</div> ho
|}
!! html/php
<table>
<tr>
-<th> hi <div class="!!">ha</div> ho
+<th>hi <div class="!!">ha</div> ho
</th></tr></table>
!! html/parsoid
<table>
-<tbody><tr><th> hi <div class="!!" data-parsoid='{"stx":"html"}'>ha</div> ho</th></tr>
+<tbody><tr><th>hi <div class="!!" data-parsoid='{"stx":"html"}'>ha</div> ho</th></tr>
</tbody></table>
!! end
! and || in element attributes should not be parsed as <th>/<td>
!! wikitext
{|
-| <div style="color: red !important;" data-contrived="put this here ||">hi</div>
+|<div style="color: red !important;" data-contrived="put this here ||">hi</div>
|}
!! html/php
<table>
<tr>
-<td> <div style="color: red !important;" data-contrived="put this here ||">hi</div>
+<td><div style="color: red !important;" data-contrived="put this here ||">hi</div>
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr><td> <div style="color: red !important;" data-contrived="put this here ||" data-parsoid='{"stx":"html"}'>hi</div></td></tr>
+<tbody><tr><td><div style="color: red !important;" data-contrived="put this here ||" data-parsoid='{"stx":"html"}'>hi</div></td></tr>
</tbody></table>
!! end
parsoid=wt2html
!! wikitext
{|
-| style="color: red !important;" data-contrived="put this here ||" | foo
+|style="color: red !important;" data-contrived="put this here ||"|foo
|}
!! html/php
<table>
<tr>
-<td> style="color: red !important;" data-contrived="put this here </td>
-<td> foo
+<td>style="color: red !important;" data-contrived="put this here</td>
+<td>foo
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr><td> style="color: red !important;" data-contrived="put this here </td><td data-parsoid='{"stx":"row","a":{"\"":null},"sa":{"\"":""},"autoInsertedEnd":true}'> foo</td></tr>
+<tbody><tr><td>style="color: red !important;" data-contrived="put this here</td><td data-parsoid='{"stx":"row","a":{"\"":null},"sa":{"\"":""},"autoInsertedEnd":true}'>foo</td></tr>
</tbody></table>
!! end
<p>ho">ha</div>
</p>
!! html/parsoid
-<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"ho\">ha</div>"}},"i":0}}]}'>ho">ha</span>
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"ho\">ha</div>"}},"i":0}}]}'>ho">ha</p>
!! end
!! test
<references />
!! html/parsoid
-<p><sup about="#mwt2" class="mw-ref" id="cite_ref-hi|ho_1-0" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<ref name=\"hi|ho\">ha</ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-hi|ho-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p>
+<p><sup about="#mwt2" class="mw-ref" id="cite_ref-hi|ho_1-0" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<ref name=\"hi|ho\">ha</ref>"}},"i":0}}]}'><a href="./Parser_test#cite_note-hi|ho-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-hi|ho-1" id="cite_note-hi|ho-1"><a href="./Main_Page#cite_ref-hi|ho_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-hi|ho-1" class="mw-reference-text">ha</span></li></ol>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-hi|ho-1" id="cite_note-hi|ho-1"><a href="./Parser_test#cite_ref-hi|ho_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-hi|ho-1" class="mw-reference-text">ha</span></li></ol>
!! end
## We don't support roundtripping of these attributes in Parsoid.
parsoid=wt2html
!! wikitext
{| <span>boo</span> style='border:1px solid black'
-| <span>boo</span> style='color:blue' | 1
-|<span>boo</span> style='color:blue'| 2
+| <span>boo</span> style='color:blue' |1
+|<span>boo</span> style='color:blue'|2
|}
!! html/php
<table style="border:1px solid black">
<tr>
-<td style="color:blue"> 1
+<td style="color:blue">1
</td>
-<td style="color:blue"> 2
+<td style="color:blue">2
</td></tr></table>
!! html/parsoid
<table style="border:1px solid black">
<tr>
-<td style="color:blue"> 1</td>
-<td style="color:blue"> 2</td>
+<td style="color:blue">1</td>
+<td style="color:blue">2</td>
</tr>
</table>
!! end
|}
!! wikitext/edited
{| <span>boo</span> style='border:1px solid black'
-| <span>boo</span> style='color:blue' |abc
-|<span>boo</span> style='color:blue'|xyz
+| <span>boo</span> style='color:blue' | abc
+|<span>boo</span> style='color:blue'| xyz
|}
!! end
</td>
<td style="color:red;">Foo
</td>
-<td> style="color:red;"</td>
+<td>style="color:red;"</td>
<td>Bar
</td>
<td style="color:red;">Foo
<references />
!! html/parsoid
<table>
-<tbody><tr><td style="background:#f9f9f9;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_7","href":"./Template:Table_attribs_7"},"params":{},"i":0}}]}'>Foo<sup class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></s></td></tr>
+<tbody><tr><td style="background:#f9f9f9;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_7","href":"./Template:Table_attribs_7"},"params":{},"i":0}}]}'>Foo<sup class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{},"body":{"id":"mw-reference-text-cite_note-1"}}'><a href="./Parser_test#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></s></td></tr>
</tbody></table>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Parser_test#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
!! end
!! test
{|
|-
-! foo
+!foo
|}
!! html/*
<table>
<tr>
-<th> foo
+<th>foo
</th></tr></table>
!! end
{|
|-
-| foo
+|foo
|}
!! html/*
<table>
<tr>
-<td> foo
+<td>foo
</td></tr></table>
!! end
parsoid=wt2html,html2html
!! wikitext
{|
-| style=| hello
+| style=|hello
|}
!! html/php
<table>
<tr>
-<td style=""> hello
+<td style="">hello
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr><td style=""> hello</td></tr>
+<tbody><tr><td style="">hello</td></tr>
</tbody></table>
!! end
!! wikitext
{|
<!-- c0 -->
-| foo
+|foo
<!-- c1 -->
|-<!-- c2 -->
<!-- c3 -->
!! html
<table>
<tr>
-<td> foo
+<td>foo
</td></tr>
<tr>
<td>
!! wikitext
{|<!--c1--><!--c2-->
|-<!--c3-->
-| x
+|x
|}
!! html/php+tidy
<table>
<tbody><tr>
-<td> x
+<td>x
</td></tr></tbody></table>
!! html/parsoid
<table><!--c1--><!--c2-->
<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'><!--c3-->
-<td data-parsoid='{"autoInsertedEnd":true}'> x</td></tr>
+<td data-parsoid='{"autoInsertedEnd":true}'>x</td></tr>
</tbody></table>
!! end
Table cell with a single comment
!! wikitext
{|
-| <!-- c1 -->
-| a
+|<!-- c1 -->
+|a
|}
!! html
<table>
<tr>
<td>
</td>
-<td> a
+<td>a
</td></tr></table>
!! end
{|
|a
<!--c1-->
-<!--c2-->| b
+<!--c2-->|b
|}
!! html
<table>
<tr>
<td>a
</td>
-<td> b
+<td>b
</td></tr></table>
!! html/parsoid
<table>
<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'>a</td>
<!--c1-->
-<!--c2--><td data-parsoid='{"autoInsertedEnd":true}'> b</td></tr>
+<!--c2--><td data-parsoid='{"autoInsertedEnd":true}'>b</td></tr>
</tbody></table>
!! end
Build table with {{!}}
!! wikitext
{{{!}} class="wikitable"
-! header
-! second header
+!header
+!second header
{{!}}- style="color:red;"
-{{!}} data {{!}}{{!}} style="color:red;" {{!}} second data
+{{!}}data{{!}}{{!}} style="color:red;" {{!}}second data
{{!}}}
!! html
<table class="wikitable">
<tr>
-<th> header
+<th>header
</th>
-<th> second header
+<th>second header
</th></tr>
<tr style="color:red;">
-<td> data </td>
-<td style="color:red;"> second data
+<td>data</td>
+<td style="color:red;">second data
</td></tr></table>
!! end
Build table with pipe as data
!! wikitext
{| class="wikitable"
-! header
-! second header
+!header
+!second header
|- style="color:red;"
-| data || style="color:red;" | second data
+|data|| style="color:red;" |second data
|-
-| style="color:red;" | data with | || style="color:red;" | second data with |
+| style="color:red;" |data with | || style="color:red;" | second data with |
|-
-|| data with | ||| second data with |
+||data with | |||second data with |
|}
!! html
<table class="wikitable">
<tr>
-<th> header
+<th>header
</th>
-<th> second header
+<th>second header
</th></tr>
<tr style="color:red;">
-<td> data </td>
-<td style="color:red;"> second data
+<td>data</td>
+<td style="color:red;">second data
</td></tr>
<tr>
-<td style="color:red;"> data with | </td>
-<td style="color:red;"> second data with |
+<td style="color:red;">data with |</td>
+<td style="color:red;">second data with |
</td></tr>
<tr>
-<td> data with | </td>
-<td> second data with |
+<td>data with |</td>
+<td>second data with |
</td></tr></table>
!! end
Build table with wikilink
!! wikitext
{| class="wikitable"
-! header || second header
+!header||second header
|- style="color:red;"
-| data [[Main Page|linktext]] || second data [[Main Page|linktext]]
+|data [[Main Page|linktext]]||second data [[Main Page|linktext]]
|-
-| data || second data [[Main Page|link|text with pipe]]
+|data||second data [[Main Page|link|text with pipe]]
|}
!! html
<table class="wikitable">
<tr>
-<th> header </th>
-<th> second header
+<th>header</th>
+<th>second header
</th></tr>
<tr style="color:red;">
-<td> data <a href="/wiki/Main_Page" title="Main Page">linktext</a> </td>
-<td> second data <a href="/wiki/Main_Page" title="Main Page">linktext</a>
+<td>data <a href="/wiki/Main_Page" title="Main Page">linktext</a></td>
+<td>second data <a href="/wiki/Main_Page" title="Main Page">linktext</a>
</td></tr>
<tr>
-<td> data </td>
-<td> second data <a href="/wiki/Main_Page" title="Main Page">link|text with pipe</a>
+<td>data</td>
+<td>second data <a href="/wiki/Main_Page" title="Main Page">link|text with pipe</a>
</td></tr></table>
!! end
<td>foo</td></tr></tbody></table>
!! end
+## Remex doesn't account for fostered content.
!! test
Fostered content in tables: Plain text
!! options
-parsoid=wt2html,html2html
+parsoid=wt2html
!! wikitext
{|
|-
a
<table></table>
!! html/parsoid
-<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>a</p><table>
-<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-
-</tr></tbody></table>
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>
+a</p>
+<table>
+<tbody><tr class="mw-empty-elt" data-parsoid='{"startTagSrc":"|-"}'></tr></tbody></table>
!! end
!! test
!! wikitext
{|
|-
-{{table_attribs_4}} || a || b
+{{table_attribs_4}} ||a||b
|}
!! html/php+tidy
<table>
<tbody><tr>
-<td style="background-color:#DC241f;" width="10px"> </td>
-<td> a </td>
-<td> b
+<td style="background-color:#DC241f;" width="10px"></td>
+<td>a</td>
+<td>b
</td></tr></tbody></table>
!! html/parsoid
<table>
<tbody><tr data-parsoid='{"startTagSrc":"|-","autoInsertedEnd":true}'>
-<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," || a || b"]}'> </td><td about="#mwt1"> a </td><td about="#mwt1"> b</td></tr>
+<td style="background-color:#DC241f;" width="10px" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"table_attribs_4","href":"./Template:Table_attribs_4"},"params":{},"i":0}}," ||a||b"]}'></td><td about="#mwt1">a</td><td about="#mwt1">b</td></tr>
!! end
!! test
'''quux'''
!! end
-!! test
-Parsoid: newline inducing block nodes don't suppress <nowiki>
-!! options
-parsoid=html2wt
-!! html/parsoid
- a<h1>foo</h1>
-!! wikitext
-<nowiki> </nowiki>a
-
-= foo =
-!! end
-
!! test
Parsoid: Row-syntax table headings followed by comment & table cells
!! options
parsoid=wt2html,wt2wt
!! wikitext
{|
-! foo || bar
-<!-- foo --> || baz || quux
+!foo||bar
+<!-- foo --> ||baz||quux
|}
!! html/php
<table>
<tr>
-<th> foo </th>
-<th> bar
+<th>foo</th>
+<th>bar
</th>
-<td> baz </td>
-<td> quux
+<td>baz</td>
+<td>quux
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr><th> foo </th><th> bar
-<!-- foo --> </th><td> baz </td><td> quux</td></tr>
+<tbody><tr><th>foo</th><th>bar
+<!-- foo --></th><td> baz </td><td>quux</td></tr>
</tbody></table>
!! end
</tbody></table>
!!end
+# Note: PHP parser omits empty rows
!! test
Tables: Digest broken attributes on table and tr tag
!! options
|- || || ++ --
|- > [
|}
-!! html
+!! html/php+tidy
+<table>
+
+
+</table>
+!! html/parsoid
<table>
<tbody>
<tr class='mw-empty-elt'></tr>
</tbody></table>
!! end
+!! test
+Table with missing opening <tr> tag
+!! options
+parsoid=wt2html,wt2wt
+!! wikitext
+<table>
+<td>foo</td>
+</tr>
+</table>
+!! html+tidy
+<table>
+<tbody><tr><td>foo</td>
+</tr>
+</tbody></table>
+!! end
+
# T137406: Whitespace in the HTML
!! test
1. Generate correct wikitext for tables with thead/tbody/tfoot
!! end
!! test
-Testing serialization after deletion in references
-!! options
-parsoid={
- "modes": ["wt2wt"],
- "changes": [
- ["#x", "remove"]
- ]
-}
-!! wikitext
-hi <ref><div id="x">ho</div></ref>
-
-<references />
-!! wikitext/edited
-hi <ref></ref>
-
-<references />
-!! end
-
-!!test
-Testing serialization after deletion of table cells
-!!options
-parsoid={
- "modes": ["wt2wt", "selser"],
- "changes": [
- ["#x", "remove"]
- ]
-}
-!!wikitext
-{|
-!h1 !!h2 !!h3
-| id="x" |c1 {{!}}{{!}}{{!}}c2 |||c3
-|}
-!! wikitext/edited
-{|
-!h1 !!h2 !!h3
-|c2 |||c3
-|}
-!!end
-
-!! test
-Testing selser after addition of new row before first row (T125419)
-!! options
-parsoid={
- "modes": ["wt2wt", "selser"],
- "changes": [
- [ "tr", "before", "<tr><td>X</td></tr>" ]
- ]
-}
-!! wikitext
-{|
-|a
-|}
-!! wikitext/edited
-{|
-|X
-|-
-|a
-|}
-!! end
-
-!! test
-Serialize new table rows in a HTML table using HTML tags
-!! options
-parsoid={
- "modes": ["wt2wt", "selser"],
- "changes": [
- [ "tr", "before", "<tr><td>X</td></tr>" ]
- ]
-}
-!! wikitext
-<table><tr><td>a</td></tr></table>
-!! wikitext/edited
-<table><tr><td>X</td></tr><tr><td>a</td></tr></table>
-!! end
-
-!! test
-Serialize new table cells in a HTML row using HTML tags
-!! options
-parsoid={
- "modes": ["wt2wt", "selser"],
- "changes": [
- [ "td", "before", "<td>X</td>" ]
- ]
-}
-!! wikitext
-<table><tr><td>a</td></tr></table>
-!! wikitext/edited
-<table><tr><td>X</td><td>a</td></tr></table>
-!! end
-
-!! test
-Wikitext tables can be nested inside HTML tables
+Wikitext tables can be nested inside HTML tables
!! options
parsoid=html2wt
-!! html
+!! html/parsoid
<table data-parsoid='{"stx":"html"}'>
<tr><td>
<table>
|}
</td></tr>
</table>
-!! end
-
-!! test
-Serialize wikitext list items as HTML list items when embedded in a HTML list
-!! options
-parsoid=html2wt
-!! html
-<ul data-parsoid='{"stx": "html"}'>
-<li data-parsoid='{}'>a</li>
-<li>b</li>
-</ul>
-!! wikitext
-<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?
-# <ul><li>foo<ul>..</ul></li></ul> instead of
-# <ul><li>foo</li><ul>..</ul></ul>
-!! test
-Wikitext lists can be nested inside HTML lists
-!! options
-parsoid=html2wt
-!! html
-<ul data-parsoid='{"stx": "html"}'>
-<li data-parsoid='{"stx": "html"}'>a
-<ul><li>b</li></ul>
-</li>
-</ul>
-
-<ul data-parsoid='{"stx": "html"}'>
-<li>x
-<ul><li>y</li></ul>
-</li>
-</ul>
-!! wikitext
-<ul>
-<li>a
-* b
-</li>
-</ul>
-
-<ul>
-<li>x
-* y
-</li>
-</ul>
+!! html/php+tidy
+<table>
+<tbody><tr><td>
+<table>
+<tbody><tr>
+<td>foo
+</td></tr></tbody></table>
+</td></tr>
+</tbody></table>
!! end
###
## Example for such a section: == < ==
!! test
Link containing "#<" and "#>" % as a hex sequences- these are valid section anchors
+!! options
+title=[[Main Page]]
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
<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 & bar]]
+
+[[Foo &amp; bar]]
+!! html/php+tidy
+<p><a href="/wiki/Foo_%26_bar" title="Foo & bar">Foo & bar</a>
+</p><p><a href="/wiki/Foo_%26_bar" title="Foo & bar">Foo & bar</a>
+</p><p>[[Foo &amp; bar]]
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Foo_&_bar" title="Foo & bar">Foo & bar</a></p>
+<p><a rel="mw:WikiLink" href="./Foo_&_bar" title="Foo & bar" data-parsoid='{"stx":"simple","a":{"href":"./Foo_&_bar"},"sa":{"href":"Foo &amp; bar"}}'>Foo & bar</a></p>
+<p>[[Foo <span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>amp; bar]]</p>
+!! end
+
!! article
Foo~bar
!! text
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&action=edit&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&action=edit&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 '''bold and foolish'''"}},"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
!! wikitext
*[[Wikipedia:ro:Olteniţa]]
*[[Wikipedia:ro:Olteniţ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ţ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>
!! 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ţ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>
!! 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>
!! test
Link scenarios with escaped fragments
+!! options
+title=[[Main Page]]
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
!! html/parsoid
<p><a rel="mw:WikiLink/Interwiki" href="http://www.usemod.com/cgi-bin/mb.pl?ok" title="meatball:ok">meatball:ok</a>
<a rel="mw:WikiLink/Interwiki" href="http://www.usemod.com/cgi-bin/mb.pl?ok#foo" title="meatball:ok">ok with fragment</a>
-<a rel="mw:WikiLink/Interwiki" href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well?" title="meatball:ok as well?">ok ending with ? mark</a>
+<a rel="mw:WikiLink/Interwiki" href="http://www.usemod.com/cgi-bin/mb.pl?ok_as_well%3F" title="meatball:ok as well?">ok ending with ? mark</a>
<a rel="mw:ExtLink" class="external text" href="http://de.wikipedia.org/wiki/Foo?action=history">has query</a>
<a rel="mw:ExtLink" class="external text" href="http://de.wikipedia.org/wiki/#foo">is just fragment</a></p>
!! end
<p><a rel="mw:WikiLink" href="./Foo" title="Foo">local:local:local:local:mi:local:Foo</a></p>
!! end
+!! test
+Interwiki link with percent encoded target
+!! wikitext
+[[:es:Nueva Guip%C3%BAzcoa|Nueva Guipúzcoa]]
+!! html/php
+<p><a href="http://es.wikipedia.org/wiki/Nueva_Guip%C3%BAzcoa" class="extiw" title="es:Nueva Guipúzcoa">Nueva Guipúzcoa</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink/Interwiki" href="http://es.wikipedia.org/wiki/Nueva%20Guipúzcoa" title="es:Nueva Guipúzcoa" data-parsoid='{"stx":"piped","a":{"href":"http://es.wikipedia.org/wiki/Nueva%20Guipúzcoa"},"sa":{"href":":es:Nueva Guip%C3%BAzcoa"},"isIW":true}'>Nueva Guipúzcoa</a></p>
+!! end
+
###
### Interlanguage links
### Language links (so that searching for '### language' matches..)
<p><a rel="mw:WikiLink" href="./Constructor:foo" title="Constructor:foo" data-parsoid='{"stx":"simple","a":{"href":"./Constructor:foo"},"sa":{"href":"constructor:foo"}}'>constructor:foo</a></p>
!! end
+!! test
+Template parameter named "constructor"
+!! wikitext
+{{echo| constructor = |hi}}
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"constructor","named":true,"spc":[" "," ",""," "]},{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi"},"constructor":{"wt":""}},"i":0}}]}'>hi</p>
+!! end
+
!! article
ko:
!! text
Redirect syntax under text isn't considered a redirect
!! wikitext
some text
+
#redirect [[Main Page]]
!! html/parsoid
<p>some text</p>
!! options
parsoid=wt2html
!! wikitext
-#REDIRECT [[Main Page]]<!-- haha -->== hi ==
+#REDIRECT [[Main Page]]<!-- haha -->==hi==
!! html/parsoid
-<link rel="mw:PageProp/redirect" href="./Main_Page"/><!-- haha --><h2 id="hi"> hi </h2>
+<link rel="mw:PageProp/redirect" href="./Main_Page"/><!-- haha --><h2 id="hi">hi</h2>
!! end
!! test
!! html/parsoid
<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
-<div title="" data-parsoid='{"stx":"html","selfClose":true}'></div>
+<div title="" data-parsoid='{"stx":"html","autoInsertedEnd":true}'>
<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
<div title="bar" data-parsoid='{"stx":"html","selfClose":true}'></div>
-<div title="bar/" data-parsoid='{"stx":"html","autoInsertedEnd":true}'></div>
+<div title="bar/" data-parsoid='{"stx":"html","autoInsertedEnd":true}'></div></div>
+!! end
+
+!! test
+Elements with solidus in various attribute positions
+!! options
+parsoid=wt2html,html2html
+!! wikitext
+<div cla/ss="123">ha</div>
+
+<div / class="123">ha</div>
+
+<div class= / "123">ha</div>
+!! html/php+tidy
+<div>ha</div>
+<div class="123">ha</div>
+<div class="/">ha</div>
+!! html/parsoid
+<div data-parsoid='{"stx":"html","a":{"cla":null,"ss":null},"sa":{"cla":"","ss":"123"}}'>ha</div>
+
+<div class="123" data-parsoid='{"stx":"html"}'>ha</div>
+
+<div class="/" data-parsoid='{"stx":"html","a":{"\"123\"":null},"sa":{"\"123\"":""}}'>ha</div>
!! end
!! test
Common list
!! wikitext
*Common list
-* item 2
+*item 2
*item 3
!! html
<ul><li>Common list</li>
-<li> item 2</li>
+<li>item 2</li>
<li>item 3</li></ul>
!! end
!! wikitext
#Numbered list
#item 2
-# item 3
+#item 3
!! html
<ol><li>Numbered list</li>
<li>item 2</li>
-<li> item 3</li></ol>
+<li>item 3</li></ol>
!! end
+# the switch from level 3 to ordered should not introduce a newline between
!! test
Mixed list
!! wikitext
*Mixed list
-*# with numbers
-** and bullets
-*# and numbers
+*#with numbers
+**and bullets
+*#and numbers
*bullets again
**bullet level 2
***bullet level 3
**#Number on level 3
*#number level 2
*Level 1
-*** Level 3
-#** Level 3, but ordered
+***Level 3
+#**Level 3, but ordered
!! html
<ul><li>Mixed list
-<ol><li> with numbers</li></ol>
-<ul><li> and bullets</li></ul>
-<ol><li> and numbers</li></ol></li>
+<ol><li>with numbers</li></ol>
+<ul><li>and bullets</li></ul>
+<ol><li>and numbers</li></ol></li>
<li>bullets again
<ul><li>bullet level 2
<ul><li>bullet level 3
<li>Number on level 3</li></ol></li></ul>
<ol><li>number level 2</li></ol></li>
<li>Level 1
-<ul><li><ul><li> Level 3</li></ul></li></ul></li></ul>
-<ol><li><ul><li><ul><li> Level 3, but ordered</li></ul></li></ul></li></ol>
+<ul><li><ul><li>Level 3</li></ul></li></ul></li></ul>
+<ol><li><ul><li><ul><li>Level 3, but ordered</li></ul></li></ul></li></ol>
!! end
!! test
1. Nested mixed wikitext and html list
!! wikitext
-* hi
-* <ul><li>ho</li></ul>
-* hi
-** ho
+*hi
+*<ul><li>ho</li></ul>
+*hi
+**ho
!! html/php
-<ul><li> hi</li>
-<li> <ul><li>ho</li></ul></li>
-<li> hi
-<ul><li> ho</li></ul></li></ul>
+<ul><li>hi</li>
+<li><ul><li>ho</li></ul></li>
+<li>hi
+<ul><li>ho</li></ul></li></ul>
!! html/parsoid
-<ul><li> hi</li>
-<li> <ul data-parsoid='{"stx":"html"}'><li data-parsoid='{"stx":"html"}'>ho</li></ul></li>
-<li> hi
-<ul><li> ho</li></ul></li></ul>
+<ul><li>hi</li>
+<li><ul data-parsoid='{"stx":"html"}'><li data-parsoid='{"stx":"html"}'>ho</li></ul></li>
+<li>hi
+<ul><li>ho</li></ul></li></ul>
!! end
!! test
2. Nested mixed wikitext and html list (incompatible)
!! wikitext
-; hi
-: {{echo|<li>ho</li>}}
+;hi
+:{{echo|<li>ho</li>}}
!! html/php
-<dl><dt> hi</dt>
-<dd> <li>ho</li></dd></dl>
+<dl><dt>hi</dt>
+<dd><li>ho</li></dd></dl>
!! html/parsoid
-<dl><dt> hi</dt>
-<dd> <li about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>ho</li>"}},"i":0}}]}'>ho</li></dd></dl>
+<dl><dt>hi</dt>
+<dd><li about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>ho</li>"}},"i":0}}]}'>ho</li></dd></dl>
!! end
!! test
!! test
Nested lists 7 (skip initial nesting levels)
!! wikitext
-*** foo
+***foo
!! html
-<ul><li><ul><li><ul><li> foo</li></ul></li></ul></li></ul>
+<ul><li><ul><li><ul><li>foo</li></ul></li></ul></li></ul>
!! end
!! test
Nested lists 8 (multiple nesting transitions)
!! wikitext
-* foo
-*** bar
-** baz
-* boo
+*foo
+***bar
+**baz
+*boo
!! html
-<ul><li> foo
-<ul><li><ul><li> bar</li></ul></li>
-<li> baz</li></ul></li>
-<li> boo</li></ul>
+<ul><li>foo
+<ul><li><ul><li>bar</li></ul></li>
+<li>baz</li></ul></li>
+<li>boo</li></ul>
!! 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
!! end
+!! test
+Nested lists 10 (list and span siblings: wt2wt regression)
+!! wikitext
+*a <span>x</span>
+**b <span>y</span>
+!! html/parsoid
+<ul><li>a <span>x</span>
+<ul><li>b <span>y</span></li></ul></li></ul>
+!! end
+
!! test
2. Lists with start-of-line-transparent tokens before bullets: Template close
!! wikitext
!! test
List items are not parsed correctly following a <pre> block (T2785)
!! wikitext
-* <pre>foo</pre>
-* <pre>bar</pre>
-* zar
+*<pre>foo</pre>
+*<pre>bar</pre>
+*zar
!! html/php
-<ul><li> <pre>foo</pre></li>
-<li> <pre>bar</pre></li>
-<li> zar</li></ul>
+<ul><li><pre>foo</pre></li>
+<li><pre>bar</pre></li>
+<li>zar</li></ul>
!! html/parsoid
-<ul><li> <pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre></li>
-<li> <pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"bar"}}'>bar</pre></li>
-<li> zar</li></ul>
+<ul><li><pre typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo"}}'>foo</pre></li>
+<li><pre typeof="mw:Extension/pre" about="#mwt4" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"bar"}}'>bar</pre></li>
+<li>zar</li></ul>
!! end
+# FIXME: Might benefit from a html/parsoid since this has a template
!! test
List items from template
!! wikitext
{{inner list}}
-* item 2
+*item 2
-* item 0
+*item 0
{{inner list}}
-* item 2
+*item 2
-* item 0
-* notSOL{{inner list}}
-* item 2
+*item 0
+*notSOL{{inner list}}
+*item 2
!! html
-<ul><li> item 1</li>
-<li> item 2</li></ul>
-<ul><li> item 0</li>
-<li> item 1</li>
-<li> item 2</li></ul>
-<ul><li> item 0</li>
-<li> notSOL</li>
-<li> item 1</li>
-<li> item 2</li></ul>
+<ul><li>item 1</li>
+<li>item 2</li></ul>
+<ul><li>item 0</li>
+<li>item 1</li>
+<li>item 2</li></ul>
+<ul><li>item 0</li>
+<li>notSOL</li>
+<li>item 1</li>
+<li>item 2</li></ul>
!! end
!! test
List interrupted by empty line or heading
!! wikitext
-* foo
+*foo
-** bar
-== A heading ==
-* Another list item
+**bar
+==A heading==
+*Another list item
!! html
-<ul><li> foo</li></ul>
-<ul><li><ul><li> bar</li></ul></li></ul>
+<ul><li>foo</li></ul>
+<ul><li><ul><li>bar</li></ul></li></ul>
<h2><span class="mw-headline" id="A_heading">A heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: A heading">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
-<ul><li> Another list item</li></ul>
+<ul><li>Another list item</li></ul>
!!end
-!!test
+!! test
Multiple list tags generated by templates
!! wikitext
{{echo|<li>}}a
</li>
</li>
+
!! html+tidy
<li>a
</li><li>b
</li><li>c
</li>
-!!end
+!! html/parsoid
+<li about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>"}},"i":0}},"a"]}'>a</li>
+<li about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>"}},"i":0}},"b"]}'>b</li>
+<li about="#mwt3" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>"}},"i":0}},"c"]}'>c</li>
+!! end
-!!test
-Single-comment whitespace lines dont break lists, and neither do multi-comment whitespace lines
+!! test
+Multiple newlines in between HTML list items don't induce paragraph wrapping
!! wikitext
-*a
-<!--This line will NOT split the list-->
-*b
- <!--This line will NOT split the list either-->
-*c
- <!--foo--> <!----> <!--This line NOT split the list either-->
-*d
-!! html
-<ul><li>a</li>
-<li>b</li>
-<li>c</li>
-<li>d</li></ul>
+<ul>
+<li>hi</li>
-!!end
-!!test
-Replacing whitespace with tabs still doesn't break the list (gerrit 78327)
-!! wikitext
-*a
-<!--This line will NOT split the list-->
-*b
- <!--This line will NOT split the list either-->
-*c
+
+
+<li>ho</li>
+</ul>
+
+<dl>
+<dt>hi</dt>
+<dd>ho<div>123</div>
+</dd>
+
+
+</dl>
+!! html/php+tidy
+<ul>
+<li>hi</li>
+
+
+
+
+<li>ho</li>
+</ul>
+<dl>
+<dt>hi</dt>
+<dd>ho<div>123</div>
+</dd>
+
+
+</dl>
+!! end
+
+!!test
+Single-comment whitespace lines dont break lists, and neither do multi-comment whitespace lines
+!! wikitext
+*a
+<!--This line will NOT split the list-->
+*b
+ <!--This line will NOT split the list either-->
+*c
+ <!--foo--> <!----> <!--This line NOT split the list either-->
+*d
+!! html
+<ul><li>a</li>
+<li>b</li>
+<li>c</li>
+<li>d</li></ul>
+
+!!end
+
+!!test
+Replacing whitespace with tabs still doesn't break the list (gerrit 78327)
+!! wikitext
+*a
+<!--This line will NOT split the list-->
+*b
+ <!--This line will NOT split the list either-->
+*c
<!--foo--> <!----> <!--This line NOT split the list
either-->
*d
!!options
parsoid=wt2html,wt2wt
!! wikitext
-* foo
-* <li>li-hack
-* {{echo|<li>templated li-hack}}
-* <!--foo--> <li> unsupported li-hack with preceding comments
+*foo
+*<li>li-hack
+*{{echo|<li>templated li-hack}}
+*<!--foo--><li> unsupported li-hack with preceding comments
<ul>
<li><li>not a li-hack
</li>
</ul>
!! html+tidy
-<ul><li> foo</li>
-<li class="mw-empty-elt"> </li><li>li-hack</li>
-<li class="mw-empty-elt"> </li><li>templated li-hack</li>
-<li class="mw-empty-elt"> </li><li> unsupported li-hack with preceding comments</li></ul>
+<ul><li>foo</li>
+<li class="mw-empty-elt"></li><li>li-hack</li>
+<li class="mw-empty-elt"></li><li>templated li-hack</li>
+<li class="mw-empty-elt"></li><li> unsupported li-hack with preceding comments</li></ul>
<ul>
<li class="mw-empty-elt"></li><li>not a li-hack
</li>
</ul>
!! html/parsoid
<ul><li> foo</li>
-<li data-parsoid='{"stx":"html","autoInsertedEnd":true,"liHackSrc":"* "}'>li-hack</li>
-<li about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,,"pi":[[{"k":"1"}]]}' data-mw='{"parts":["* ",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>templated li-hack"}},"i":0}}]}'>templated li-hack</li>
-<li data-parsoid='{"autoInsertedEnd":true}'> <!--foo--> </li><li data-parsoid='{"stx":"html","autoInsertedEnd":true}'> unsupported li-hack with preceding comments</li></ul>
+<li data-parsoid='{"stx":"html","autoInsertedEnd":true,"liHackSrc":"*"}'>li-hack</li>
+<li about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,,"pi":[[{"k":"1"}]]}' data-mw='{"parts":["*",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<li>templated li-hack"}},"i":0}}]}'>templated li-hack</li>
+<li data-parsoid='{"autoInsertedEnd":true}'><!--foo--></li><li data-parsoid='{"stx":"html","autoInsertedEnd":true}'>unsupported li-hack with preceding comments</li></ul>
<ul data-parsoid='{"stx":"html"}'>
<li class="mw-empty-elt" data-parsoid='{"stx":"html","autoInsertedEnd":true}'></li><li data-parsoid='{"stx":"html"}'>not a li-hack
!! test
Parsoid: Make sure nested lists are serialized on their own line even if HTML contains no newlines
-!! options
-parsoid
!! wikitext
-# foo
-## bar
-* foo
-** bar
-: foo
-:: bar
-!! html
+#foo
+##bar
+
+*foo
+**bar
+
+:foo
+::bar
+!! 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>
+<li>foo<ol>
+<li>bar</li>
</ol></li>
</ol><ul>
-<li> foo<ul>
-<li> bar</li>
+<li>foo<ul>
+<li>bar</li>
</ul></li>
</ul><dl>
-<dd> foo<dl>
-<dd> bar</dd>
+<dd>foo<dl>
+<dd>bar</dd>
</dl></dd>
</dl>
!! end
!! test
Parsoid: Test of whitespace serialization with Templated bullets
!! options
-parsoid
+parsoid=wt2html
!! wikitext
* {{bullet}}
!! html/parsoid
<div>
<ul><li>a</li></ul></div><div>
<li>b</li></div>
-!! html+parsoid
+!! html/parsoid
<div><ul>
<li>a</li>
</ul></div>
!! test
Unbalanced closing non-block tags don't break a list
+!! options
+parsoid=wt2html,html2html
!! wikitext
<span>
*a</span><span>
<ul><li>a<span></span></li>
<li>b</li></ul>
!! html/parsoid
-<span>
-<ul>
-<li>a<span></span></li>
-<li>b</li>
-</ul>
-</span>
+<p><span data-parsoid='{"stx":"html","autoInsertedEnd":true}'></span></p>
+<ul><li>a<span data-parsoid='{"stx":"html","autoInsertedEnd":true}'></span></li>
+<li>b</li></ul>
!! end
# Parsoid does some post-dom-building cleanup
!! options
parsoid=wt2html,wt2wt,html2html
!! wikitext
-# <s> a
-# b </s>
+#<s> a
+#b </s>
!! html/php+tidy
-<ol><li> <s> a</s></li><s>
-</s><li><s> b </s></li></ol>
+<ol><li><s> a</s></li><s>
+</s><li><s>b </s></li></ol>
!! html/parsoid
-<ol><li> <s> a</s><s></s></li>
-<li><s> b </s></li></ol>
+<ol><li><s> a</s></li>
+<li><s>b </s></li></ol>
!! end
# Output is ugly because of all the misnested tag fixups.
-# Remex is wrapping p-tags around empty elements.
-# Parsoid has special-case handling of this pattern of
-# wrapping lists in formatting tags.
-# FIXME: Should we remove this code from Parsoid? Or add
-# special support in Remex? If the latter, maybe just wait
-# for Parsoid to become the default parser.
-# See T70395.
-!!test
+!! test
1. List embedded in a formatting tag
!! wikitext
<small>
-* foo
+*foo
</small>
!! html/php+tidy
<p><small>
-</small></p><small><ul><li> foo</li></ul></small><small></small><p><small></small>
+</small></p><small><ul><li>foo</li></ul></small><small></small><p><small></small>
</p>
!! html/parsoid
-<small>
-<ul>
-<li> foo</li>
-</ul>
-</small>
-!!end
+<p><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'></small></p><small data-parsoid='{"stx":"html","autoInsertedEnd":true,"autoInsertedStart":true}'>
+<ul><li data-parsoid='{}'>foo</li></ul></small>
+<p><small data-parsoid='{"stx":"html","autoInsertedStart":true}'></small></p>
+!! end
-# Output is ugly because of all the misnested tag fixups
-# Remex is wrapping p-tags around empty elements.
-# Parsoid has code that strips useless p-tags.
-!!test
+# Output is ugly because of all the misnested tag fixups.
+!! test
2. List embedded in a formatting tag in a misnested way
!! wikitext
<small>
</small></p><small></small><ul><small><li>a</li>
</small><li><small>b</small></li></ul>
!! html/parsoid
-<small></small>
-<ul><small>
-<li>a</li>
-</small>
-<li><small>b</small></li>
-</ul>
-!!end
+<p><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'></small></p>
+<ul><small data-parsoid='{"stx":"html","autoInsertedEnd":true,"autoInsertedStart":true}'><li>a</li></small>
+<li><small data-parsoid='{"stx":"html","autoInsertedStart":true}'>b</small></li></ul>
+!! end
+# Output is ugly because of all the misnested tag fixups.
!! test
-Table with missing opening <tr> tag
-!! options
-parsoid=wt2html,wt2wt
+3. List embedded in a formatting tag in a misnested way
!! wikitext
-<table>
-<td>foo</td>
-</tr>
-</table>
-!! html+tidy
-<table>
-<tbody><tr><td>foo</td>
-</tr>
-</tbody></table>
+<small>
+
+** 123</small>
+!! html/php+tidy
+<p><small>
+</small></p><small></small><ul><small></small><li><small></small><ul><small></small><li><small>123</small></li></ul></li></ul>
+!! html/parsoid
+<p><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'></small></p>
+
+<ul><li><ul><li data-parsoid='{}'><small data-parsoid='{"stx":"html","autoInsertedStart":true}'> 123</small></li></ul></li></ul>
!! end
###
!! test
Magic Words LOCAL (UTC)
!! wikitext
-* {{LOCALMONTH}}
-* {{LOCALMONTH1}}
-* {{LOCALMONTHNAME}}
-* {{LOCALMONTHNAMEGEN}}
-* {{LOCALMONTHABBREV}}
-* {{LOCALDAY}}
-* {{LOCALDAY2}}
-* {{LOCALDAYNAME}}
-* {{LOCALYEAR}}
-* {{LOCALTIME}}
-* {{LOCALHOUR}}
-* {{LOCALWEEK}}
-* {{LOCALDOW}}
-* {{LOCALTIMESTAMP}}
-!! html
-<ul><li> 01</li>
-<li> 1</li>
-<li> January</li>
-<li> January</li>
-<li> Jan</li>
-<li> 1</li>
-<li> 01</li>
-<li> Thursday</li>
-<li> 1970</li>
-<li> 00:02</li>
-<li> 00</li>
-<li> 1</li>
-<li> 4</li>
-<li> 19700101000203</li></ul>
+*{{LOCALMONTH}}
+*{{LOCALMONTH1}}
+*{{LOCALMONTHNAME}}
+*{{LOCALMONTHNAMEGEN}}
+*{{LOCALMONTHABBREV}}
+*{{LOCALDAY}}
+*{{LOCALDAY2}}
+*{{LOCALDAYNAME}}
+*{{LOCALYEAR}}
+*{{LOCALTIME}}
+*{{LOCALHOUR}}
+*{{LOCALWEEK}}
+*{{LOCALDOW}}
+*{{LOCALTIMESTAMP}}
+!! html
+<ul><li>01</li>
+<li>1</li>
+<li>January</li>
+<li>January</li>
+<li>Jan</li>
+<li>1</li>
+<li>01</li>
+<li>Thursday</li>
+<li>1970</li>
+<li>00:02</li>
+<li>00</li>
+<li>1</li>
+<li>4</li>
+<li>19700101000203</li></ul>
!! end
# 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:''{{PAGENAME}}''}}"}' data-mw='{"attribs":[[{"txt":"content"},{"html":"DISPLAYTITLE:<i data-parsoid='{\"dsr\":[15,31,2,2]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[17,29,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAME\",\"function\":\"pagename\"},\"params\":{},\"i\":0}}]}'>Main Page</span></i>"}]]}'/>
+<meta property="mw:PageProp/displaytitle" content="Parser test" about="#mwt3" typeof="mw:ExpandedAttrs" data-parsoid='{"src":"{{DISPLAYTITLE:''{{PAGENAME}}''}}"}' data-mw='{"attribs":[[{"txt":"content"},{"html":"DISPLAYTITLE:<i data-parsoid='{\"dsr\":[15,31,2,2]}'><span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[17,29,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"PAGENAME\",\"function\":\"pagename\"},\"params\":{},\"i\":0}}]}'>Parser test</span></i>"}]]}'/>
!! end
# NOTE: mw:ExpandedAttrs is not the best typeof here. mw:Transclusion is better.
<p><a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc822">RFC 822</a>
</p>
!! html/parsoid
-<p><a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external text">RFC 822</a></p>
+<p><a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external mw-magiclink">RFC 822</a></p>
!! end
!! test
<p>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc822">RFC 822</a> but thisRFC 822 is not RFC 822linked.
</p>
!! html/parsoid
-<p>This is <a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external text">RFC 822</a> but thisRFC 822 is not RFC 822linked.</p>
+<p>This is <a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external mw-magiclink">RFC 822</a> but thisRFC 822 is not RFC 822linked.</p>
!! end
!! test
822
</p>
!! html/parsoid
-<p><a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external text">RFC <span typeof="mw:Entity" data-parsoid='{"src":"&nbsp;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#0160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#xA0;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#Xa0;","srcContent":" "}'> </span> 822</a>
+<p><a href="https://tools.ietf.org/html/rfc822" rel="mw:ExtLink" class="external mw-magiclink">RFC <span typeof="mw:Entity" data-parsoid='{"src":"&nbsp;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#0160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#xA0;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#Xa0;","srcContent":" "}'> </span> 822</a>
RFC
822</p>
!! end
<p><a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a>
</p>
!! html/parsoid
-<p><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external text">PMID 1234</a></p>
+<p><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external mw-magiclink">PMID 1234</a></p>
!! end
!! test
<p>This is <a class="external mw-magiclink-pmid" rel="nofollow" href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract">PMID 1234</a> but thisPMID 1234 is not PMID 1234linked.
</p>
!! html/parsoid
-<p>This is <a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external text">PMID 1234</a> but thisPMID 1234 is not PMID 1234linked.</p>
+<p>This is <a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external mw-magiclink">PMID 1234</a> but thisPMID 1234 is not PMID 1234linked.</p>
!! end
!! test
1234
</p>
!! html/parsoid
-<p><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external text">PMID <span typeof="mw:Entity" data-parsoid='{"src":"&nbsp;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#0160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#xA0;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#Xa0;","srcContent":" "}'> </span> 1234</a>
+<p><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external mw-magiclink">PMID <span typeof="mw:Entity" data-parsoid='{"src":"&nbsp;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#0160;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#xA0;","srcContent":" "}'> </span><span typeof="mw:Entity" data-parsoid='{"src":"&#Xa0;","srcContent":" "}'> </span> 1234</a>
PMID
1234</p>
!! end
!! html
<p>foo
</p>
-<ul><li> item 1</li></ul>
+<ul><li>item 1</li></ul>
!! html/parsoid
<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"{{echo|echo}}","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
-<ul about="#mwt4" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"{{echo|inner list}} ","href":"./Template:Inner_list"},"params":{},"i":0}}]}'><li> item 1</li></ul>
+<ul about="#mwt4" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"{{echo|inner list}} ","href":"./Template:Inner_list"},"params":{},"i":0}}]}'><li>item 1</li></ul>
!! end
## Regression test; the output here isn't really that interesting.
Abort table cell attribute parsing on wikilink
!! wikitext
{|
-| testing [[one|two]] | three || four
-| testing one two | three || four
-| testing="[[one|two]]" | three || four
+|testing [[one|two]] |three||four
+|testing one two |three||four
+|testing="[[one|two]]" |three||four
|}
!! html/php
<table>
<tr>
-<td> testing <a href="/index.php?title=One&action=edit&redlink=1" class="new" title="One (page does not exist)">two</a> | three </td>
-<td> four
+<td>testing <a href="/index.php?title=One&action=edit&redlink=1" class="new" title="One (page does not exist)">two</a> |three</td>
+<td>four
</td>
-<td> three </td>
-<td> four
+<td>three</td>
+<td>four
</td>
-<td> testing="<a href="/index.php?title=One&action=edit&redlink=1" class="new" title="One (page does not exist)">two</a>" | three </td>
-<td> four
+<td>testing="<a href="/index.php?title=One&action=edit&redlink=1" class="new" title="One (page does not exist)">two</a>" |three</td>
+<td>four
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'> testing <a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a> | three </td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'> four</td>
-<td data-parsoid='{"a":{"testing":null,"one":null,"two":null},"sa":{"testing":"","one":"","two":""},"autoInsertedEnd":true}'> three </td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'> four</td>
-<td> testing="<a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a>" | three </td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'> four</td></tr>
+<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'>testing <a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a> |three</td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'>four</td>
+<td data-parsoid='{"a":{"testing":null,"one":null,"two":null},"sa":{"testing":"","one":"","two":""},"autoInsertedEnd":true}'>three</td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'>four</td>
+<td>testing="<a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"piped","a":{"href":"./One"},"sa":{"href":"one"}}'>two</a>" |three</td><td data-parsoid='{"stx":"row","autoInsertedEnd":true}'>four</td></tr>
</tbody></table>
!! end
Don't abort table cell attribute parsing if wikilink is found in template arg
!! wikitext
{|
-| Test {{#tag:ref|One two "[[three]]" four}}
+|Test {{#tag:ref|One two "[[three]]" four}}
|}
!! html/parsoid
<table>
-<tbody><tr><td> Test <ref about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"#tag:ref","function":"tag"},"params":{"1":{"wt":"One two \"[[three]]\" four"}},"i":0}}]}'>One two "<a rel="mw:WikiLink" href="./Three" title="Three">three</a>" four</ref></td></tr>
+<tbody><tr><td>Test <ref about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"#tag:ref","function":"tag"},"params":{"1":{"wt":"One two \"[[three]]\" four"}},"i":0}}]}'>One two "<a rel="mw:WikiLink" href="./Three" title="Three">three</a>" four</ref></td></tr>
</tbody></table>
!! end
</p>
!! end
+!! test
+Template from non-includable namespace
+!! options
+wgNonincludableNamespaces=10
+!! wikitext
+{{echo|uh oh!}}
+!! html
+<p><a href="/wiki/Template:Echo" title="Template:Echo">Template:Echo</a>
+</p>
+!! end
+
!! article
Template:table
!! text
</p>
<table>
<tr>
-<td> 1 </td>
-<td> 2
+<td>1</td>
+<td>2
</td></tr>
<tr>
-<td> 3 </td>
-<td> 4
+<td>3</td>
+<td>4
</td></tr></table>
!! end
</p>
<table>
<tr>
-<td> 1 </td>
-<td> 2
+<td>1</td>
+<td>2
</td></tr>
<tr>
-<td> 3 </td>
-<td> 4
+<td>3</td>
+<td>4
</td></tr></table>
!! end
<includeonly>
!! html/php
!! html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>"}'/>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>"}' data-mw='{"src":"<includeonly>"}'/>
!! end
## We used to, but no longer wt2wt this test since the default serializer
!! options
parsoid=wt2html,html2html
!! wikitext
-<!-- comment --><noinclude><!-- comment --></noinclude><!-- comment -->== hu ==
+<!-- comment --><noinclude><!-- comment --></noinclude><!-- comment -->==hu==
<noinclude>
some
-</noinclude>* stuff
+</noinclude>*stuff
+*here
+
+<noinclude>
+some</noinclude>* stuff
* here
-<includeonly>can have stuff</includeonly>=== here ===
+<includeonly>can have stuff</includeonly>===here===
!! html/php
<h2><span class="mw-headline" id="hu">hu</span></h2>
<p>some
</p>
-<ul><li> stuff</li>
-<li> here</li></ul>
+<ul><li>stuff</li>
+<li>here</li></ul>
+<p><br />
+some* stuff
+</p>
+<ul><li>here</li></ul>
<h3><span class="mw-headline" id="here">here</span></h3>
!! html/parsoid
-<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"</noinclude>"}'/><!-- comment --><h2 id="hu"> hu </h2>
+<!-- comment --><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/><!-- comment --><meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"</noinclude>"}'/><!-- comment --><h2 id="hu">hu</h2>
<meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/>
<p>some</p>
-<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"</noinclude>"}'/><ul><li> stuff</li>
-<li> here</li></ul>
+<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"</noinclude>"}'/><ul><li>stuff</li>
+<li>here</li></ul>
+
+<meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/>
+<p>some<meta typeof="mw:Includes/NoInclude/End" data-parsoid='{"src":"</noinclude>"}'/>* stuff</p>
+<ul><li>here</li></ul>
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>can have stuff</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><h3 id="here"> here </h3>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>can have stuff</includeonly>"}' data-mw='{"src":"<includeonly>can have stuff</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><h3 id="here">here</h3>
!! end
<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<table></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<table></table>\nc"}},"i":0}},"d"]}' data-parsoid='{"pi":[[{"k":"1"}]]}'>ab</p><span about="#mwt2">
!! 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>
!! 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>
!! wikitext
{{Precedence5|Bullet}}
!! html/php
-<ul><li> Bar</li></ul>
+<ul><li>Bar</li></ul>
!! html/parsoid
-<ul typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"Precedence5","href":"./Template:Precedence5"},"params":{"1":{"wt":"Bullet"}},"i":0}}]}'><li> Bar</li></ul>
+<ul typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"Precedence5","href":"./Template:Precedence5"},"params":{"1":{"wt":"Bullet"}},"i":0}}]}'><li>Bar</li></ul>
!! end
!! test
{{Preprocessor precedence 9|Four|Bullet|1|2}}
!! html/php
<dl><dt>4</dt>
-<dd> {Four}</dd>
+<dd>{Four}</dd>
<dt>5</dt>
-<dd> </dd></dl>
-<ul><li> Bar</li></ul>
+<dd></dd></dl>
+<ul><li>Bar</li></ul>
<dl><dt>6</dt>
-<dd> Four</dd>
+<dd>Four</dd>
<dt>7</dt>
-<dd> {Bullet}</dd></dl>
+<dd>{Bullet}</dd></dl>
!! html/parsoid
<dl about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"Preprocessor precedence 9","href":"./Template:Preprocessor_precedence_9"},"params":{"1":{"wt":"Four"},"2":{"wt":"Bullet"},"3":{"wt":"1"},"4":{"wt":"2"}},"i":0}}]}'>
{{Preprocessor precedence 10|Three|raw2|Bullet|1|2}}
!! html/php
<dl><dt>1</dt>
-<dd> raw</dd>
+<dd>raw</dd>
<dt>2</dt>
-<dd> -</dd></dl>
-<ul><li> Bar-</li></ul>
+<dd>-</dd></dl>
+<ul><li>Bar-</li></ul>
<dl><dt>3</dt>
-<dd> -Three-</dd>
+<dd>-Three-</dd>
<dt>4</dt>
-<dd> raw2</dd>
+<dd>raw2</dd>
<dt>5</dt>
-<dd> -</dd></dl>
-<ul><li> Bar-</li></ul>
+<dd>-</dd></dl>
+<ul><li>Bar-</li></ul>
<dl><dt>6</dt>
-<dd> -Three-</dd>
+<dd>-Three-</dd>
<dt>7</dt>
-<dd> raw2</dd></dl>
+<dd>raw2</dd></dl>
!! html/parsoid
<dl about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"Preprocessor precedence 10","href":"./Template:Preprocessor_precedence_10"},"params":{"1":{"wt":"Three"},"2":{"wt":"raw2"},"3":{"wt":"Bullet"},"4":{"wt":"1"},"5":{"wt":"2"}},"i":0}}]}'>
parsoid=wt2html
!! wikitext
This form breaks the template, which is unfortunate:
-* {{echo|foo-{bar}bat}}
+*{{echo|foo-{bar}bat}}
But if the broken language converter markup is inside an extension
tag, nothing bad happens:
-* <nowiki>foo-{bar}bat</nowiki>
-* {{echo|<nowiki>foo-{bar}bat</nowiki>}}
-* <pre>foo-{bar}bat</pre>
-* {{echo|<pre>foo-{bar}bat</pre>}}
+*<nowiki>foo-{bar}bat</nowiki>
+*{{echo|<nowiki>foo-{bar}bat</nowiki>}}
+*<pre>foo-{bar}bat</pre>
+*{{echo|<pre>foo-{bar}bat</pre>}}
<tag>foo-{bar}bat</tag>
{{echo|<tag>foo-{bar}bat</tag>}}
!! html/php+tidy
<p>This form breaks the template, which is unfortunate:
</p>
-<ul><li> {{echo|foo-{bar}bat}}</li></ul>
+<ul><li>{{echo|foo-{bar}bat}}</li></ul>
<p>But if the broken language converter markup is inside an extension
tag, nothing bad happens:
</p>
-<ul><li> foo-{bar}bat</li>
-<li> foo-{bar}bat</li>
-<li> <pre>foo-{bar}bat</pre></li>
-<li> <pre>foo-{bar}bat</pre></li></ul>
+<ul><li>foo-{bar}bat</li>
+<li>foo-{bar}bat</li>
+<li><pre>foo-{bar}bat</pre></li>
+<li><pre>foo-{bar}bat</pre></li></ul>
<pre>'foo-{bar}bat'
array (
)
<li><span typeof="mw:Nowiki">foo-{bar}bat</span></li>
<li><span typeof="mw:Transclusion mw:Nowiki" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<nowiki>foo-{bar}bat</nowiki>"}},"i":0}}]}'>foo-{bar}bat</span></li>
<li><pre typeof="mw:Extension/pre" data-mw='{"name":"pre","attrs":{},"body":{"extsrc":"foo-{bar}bat"}}'>foo-{bar}bat</pre></li>
-<li><pre typeof="mw:Transclusion mw:Extension/pre" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<pre>foo-{bar}bat</pre>"}},"i":0}}]}'>foo-{bar}bat</pre></li>
+<li><pre typeof="mw:Extension/pre mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<pre>foo-{bar}bat</pre>"}},"i":0}}]}'>foo-{bar}bat</pre></li>
</ul>
<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{},"body":{"extsrc":"foo-{bar}bat"}}'></pre> <pre typeof="mw:Extension/tag mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<tag>foo-{bar}bat</tag>"}},"i":0}}]}'></pre>
!! end
!! options
parsoid=wt2html
!! wikitext
-* [http://example.com/-{foo Example in URL]
-* [http://example.com Example in -{link} description]
-* {{echo|[http://example.com/-{foo Breaks template, however]}}
+*[http://example.com/-{foo Example in URL]
+*[http://example.com Example in -{link} description]
+*{{echo|[http://example.com/-{foo Breaks template, however]}}
!! html/php+tidy
-<ul><li> <a rel="nofollow" class="external text" href="http://example.com/-{foo">Example in URL</a></li>
-<li> <a rel="nofollow" class="external text" href="http://example.com">Example in -{link} description</a></li>
-<li> {{echo|<a rel="nofollow" class="external text" href="http://example.com/-{foo">Breaks template, however</a>}}</li></ul>
+<ul><li><a rel="nofollow" class="external text" href="http://example.com/-{foo">Example in URL</a></li>
+<li><a rel="nofollow" class="external text" href="http://example.com">Example in -{link} description</a></li>
+<li>{{echo|<a rel="nofollow" class="external text" href="http://example.com/-{foo">Breaks template, however</a>}}</li></ul>
!! html/parsoid
<ul>
<li><a rel="mw:ExtLink" class="external text" href="http://example.com/-{foo">Example in URL</a></li>
!! test
Preprocessor precedence 14: broken language converter in comment
!! wikitext
-* <!--{{foo}}--> ...should be ok
-* <!---{{foo}}--> ...extra dashes
-* {{echo|foo<!-- -{bar} -->bat}} ...should be ok
+*<!--{{foo}}-->...should be ok
+*<!---{{foo}}-->...extra dashes
+*{{echo|foo<!-- -{bar} -->bat}}...should be ok
!! html/php+tidy
-<ul><li> ...should be ok</li>
-<li> ...extra dashes</li>
-<li> foobat ...should be ok</li></ul>
+<ul><li>...should be ok</li>
+<li>...extra dashes</li>
+<li>foobat...should be ok</li></ul>
!! html/parsoid
<ul>
-<li><!--{{foo}}--> ...should be ok</li>
-<li><!---{{foo}}--> ...extra dashes</li>
-<li><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo<!-- -{bar} -->bat"}},"i":0}}]}'>foo</span><span about="#mwt1"><!-- -{bar} --></span><span about="#mwt1">bat</span> ...should be ok</li>
+<li><!--{{foo}}-->...should be ok</li>
+<li><!---{{foo}}-->...extra dashes</li>
+<li><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo<!-- -{bar} -->bat"}},"i":0}}]}'>foo</span><span about="#mwt1"><!-- -{bar} --></span><span about="#mwt1">bat</span>...should be ok</li>
</ul>
!! end
<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi {{}}"}},"i":0}}]}'>hi {{}}</p>
!! end
+# Ensure we're using a language without variants for this test; even
+# if $wgUsePigLatinVariant is true. We've picked `de` arbitrarily.
+!! test
+Preprocessor precedence 18: another rightmost wins scenario
+!! options
+parsoid=wt2html
+language=de
+!! wikitext
+{{ -{{{{1|tplarg}}} }} }-
+!! html/php
+<p>{{ -{tplarg }} }-
+</p>
+!! html/parsoid
+<p>{{ -{<span about="#mwt1" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"1"},"params":{"1":{"wt":"tplarg"}},"i":0}}]}'>tplarg</span> }} }-</p>
+!! end
+
+!! test
+Preprocessor precedence 19: break syntax
+!! options
+parsoid=wt2html
+!! wikitext
+-{{
+!! html/php
+<p>-{{
+</p>
+!! html/parsoid
+<p>-{{</p>
+!! end
+
###
### Token Stream Patcher tests
###
|c
|}
!!html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>a</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}' data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"<span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid='{\"pi\":[[]],\"dsr\":[31,38,null,null]}' data-mw='{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"b\"},\"params\":{},\"i\":0}}]}'>{{{b}}}</span>"},{"html":""}]]}'>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>a</includeonly>"}' data-mw='{"src":"<includeonly>a</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><table about="#mwt2" typeof="mw:ExpandedAttrs" data-parsoid='{"a":{"{{{b}}}":null},"sa":{"{{{b}}}":""}}' data-mw='{"attribs":[[{"txt":"{{{b}}}","html":"<span about=\"#mwt1\" typeof=\"mw:Param\" data-parsoid='{\"pi\":[[]],\"dsr\":[31,38,null,null]}' data-mw='{\"parts\":[{\"templatearg\":{\"target\":{\"wt\":\"b\"},\"params\":{},\"i\":0}}]}'>{{{b}}}</span>"},{"html":""}]]}'>
<tbody><tr><td>c</td></tr>
</tbody></table>
!!end
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>
!!end
+!! test
+Templates: Scopes should not be expanded unnecessarily
+!! options
+parsoid=wt2html,wt2wt
+!! wikitext
+{{echo|<div>a</div>}}b{{echo|
+<div>c</div>}}
+!! 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":"<div>a</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<div>c</div>"}},"i":0}}]}'>
+</span><div about="#mwt2">c</div>
+!! end
+
!!test
Templates: Inline Text: 1. Multiple template uses
!! wikitext
!!end
-# This is an edge case relating to paragraph wrapping.
-!!test
+## Parsoid drops empty elements in templates.
+!! test
Templates: Correctly encapsulate templates producing </p> tag without a corresponding <p> tag
!! wikitext
{{echo|a
b</p>}}
+!! html/php+tidy
+<p>a
+</p><p>
+b</p><p class="mw-empty-elt"></p>
!! html/parsoid
-<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb</p>"}},"i":0}}]}'>a
-b</p>
-!!end
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\nb</p>"}},"i":0}}]}'>a</p><span about="#mwt1">
+</span><p about="#mwt1">b</p>
+!! end
!!test
Templates: Links: 1. Simple example
</tbody></table>
!!end
+!! article
+Template:attribute_from_template
+!! text
+class="123"
+!! endarticle
+
+!! test
+Table cell with attribute before expanded attribute
+!! wikitext
+{|
+| align="center" {{attribute_from_template}} |456
+|}
+!! html/parsoid
+<table>
+<tbody><tr><td align="center" class="123" about="#mwt2" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"class","html":"<span about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[20,47,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"attribute_from_template\",\"href\":\"./Template:Attribute_from_template\"},\"params\":{},\"i\":0}}]}'>class=\"123\"</span>"},{"html":""}]]}'>456</td></tr>
+</tbody></table>
+!! end
+
!! test
1. Entities and nowikis inside templated attributes should be handled correctly
!! wikitext
4. Entities and nowikis inside templated attributes should be handled correctly inside templated tables
!! wikitext
{|
-| {{table_attribs_6}} hi
+|{{table_attribs_6}} hi
|}
!! html/php
<table>
<tr>
-<td style="background: red;"> hi
+<td style="background: red;">hi
</td></tr></table>
!! html/parsoid
<table>
-<tbody><tr><td style="background: red;" typeof="mw:Transclusion" about="#mwt1" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["| ",{"template":{"target":{"wt":"table_attribs_6","href":"./Template:Table_attribs_6"},"params":{},"i":0}}," hi"]}'> hi</td></tr>
+<tbody><tr><td style="background: red;" typeof="mw:Transclusion" about="#mwt1" data-parsoid='{"autoInsertedEnd":true,"pi":[[]]}' data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_6","href":"./Template:Table_attribs_6"},"params":{},"i":0}}," hi"]}'> hi</td></tr>
</tbody></table>
!! end
<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>
!!end
-!!test
+## Remex doesn't account for fostered content.
+!! test
Templates: Wiki Tables: 1a. Fostering of entire template content
!! wikitext
{|
{{echo|a}}
|}
-!! html
+!! html/php
<table>
a
<tr><td></td></tr></table>
-!! html+tidy
+!! html/php+tidy
a
<table><tbody><tr><td></td></tr></tbody></table>
+!! html/parsoid
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a"}},"i":0}},"\n|}"]}'>a</p><table about="#mwt2">
+
+</table>
!! end
!!test
</table>
!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
Templates: Wiki Tables: 2. Fostering of partial template content
!! wikitext
{|
{{echo|a
<div>b</div>}}
|}
-!! html
+!! html/php
<table>
a
<div>b</div>
<div>b</div><table>
<tbody><tr><td></td></tr></tbody></table>
!! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n<div>b</div>"}},"i":0}},"\n|}"]}'>a</p><div about="#mwt2">b</div><table about="#mwt2">
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"1"}]]}' data-mw='{"parts":["{|\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n<div>b</div>"}},"i":0}},"\n|}"]}'>a</p><div about="#mwt2">b</div><table about="#mwt2">
</table>
## a <meta> marker tag for <ref> tags and they are expanded
## much later. We are verifying that this <meta> tag usage
## doesn't prevent foster parenting.
-!!test
+!! test
Templates: Wiki Tables: 7. Fosterable <ref>s should get fostered
-!!wikitext
+!! wikitext
{{PartialTable}}<ref>foo</ref>
|}
<references />
-!!html/parsoid
-<sup about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"PartialTable","href":"./Template:PartialTable"},"params":{},"i":0}},"<ref>foo</ref>\n|}"]}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></sup><table about="#mwt2">
+!! html/parsoid
+<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"PartialTable","href":"./Template:PartialTable"},"params":{},"i":0}},"<ref>foo</ref>\n|}"]}'><sup about="#mwt3" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{},"body":{"id":"mw-reference-text-cite_note-1"}}'><a href="./Parser_test#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></p><table about="#mwt2">
<tbody>
</tbody></table>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
-!!end
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Parser_test#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+!! end
!! test
Templates: Wiki Tables: 8. Fosterable meta-tags should get fostered
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="{"parts":[{"template":{"target":{"wt":"echo_with_div","href":"./Template:Echo_with_div"},"params":{"1":{"wt":"''a"}},"i":0}}]}"><i>a</i></div>
<div about="#mwt2" typeof="mw:Transclusion" data-mw="{"parts":[{"template":{"target":{"wt":"echo_with_div","href":"./Template:Echo_with_div"},"params":{"1":{"wt":"b''c''d"}},"i":0}}]}"><i>b</i>c<i>d</i></div>
<div about="#mwt3" typeof="mw:Transclusion" data-mw="{"parts":[{"template":{"target":{"wt":"echo_with_div","href":"./Template:Echo_with_div"},"params":{"1":{"wt":"''e"}},"i":0}}]}">e</div>
{{echo|<div>foo}}
{{echo|</table>}}
!! html/parsoid
-<div about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<table>"}},"i":0}},"\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>foo"}},"i":1}},"\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"</table>"}},"i":2}}]}' data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[{"k":"1"}],[{"k":"1"}],[{"k":"1"}]]}'>foo
-</div><table about="#mwt1" data-parsoid='{"stx":"html"}'>
+<div about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","autoInsertedEnd":true,"pi":[[{"k":"1"}],[{"k":"1"}],[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<table>"}},"i":0}},"\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>foo"}},"i":1}},"\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"</table>"}},"i":2}}]}'>foo</div><span about="#mwt1">
+</span><table about="#mwt1">
</table>
!! end
</p>
!!end
-###
-### Pre-save transform tests
-###
+## Note that the templates inside the references are not wrapped
!! test
-pre-save transform: subst:
+Template nested in extension tag in template
!! options
-pst
+title=[[Main Page]]
+language=zh
+!! wikitext
+{{echo|hi<ref>[[ho|{{echo|hi}}]]</ref>}}
+{{echo|hi<ref>[http://test.com?q={{echo|ho}}]</ref>}}
+{{echo|hi<ref>-{ho|{{echo|hi}}}-</ref>}}
+<references />
+!! html/parsoid
+<p><span about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi<ref>[[ho|{{echo|hi}}]]</ref>"}},"i":0}}]}'>hi</span><sup about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{},"body":{"id":"mw-reference-text-cite_note-1"}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup>
+<span about="#mwt8" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi<ref>[http://test.com?q={{echo|ho}}]</ref>"}},"i":0}}]}'>hi</span><sup about="#mwt8" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{},"body":{"id":"mw-reference-text-cite_note-2"}}'><a href="./Main_Page#cite_note-2" style="counter-reset: mw-Ref 2;"><span class="mw-reflink-text">[2]</span></a></sup>
+<span about="#mwt13" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi<ref>-{ho|{{echo|hi}}}-</ref>"}},"i":0}}]}'>hi</span><sup about="#mwt13" class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{},"body":{"id":"mw-reference-text-cite_note-3"}}'><a href="./Main_Page#cite_note-3" style="counter-reset: mw-Ref 3;"><span class="mw-reflink-text">[3]</span></a></sup></p>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt17" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><a rel="mw:WikiLink" href="./Ho" title="Ho">hi</a></span></li><li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"><a rel="mw:ExtLink" class="external autonumber" href="http://test.com?q=ho"></a></span></li><li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text"><span typeof="mw:LanguageVariant" data-mw-variant='{"filter":{"l":["ho"],"t":"hi"}}'></span></span></li></ol>
+!! end
+
+###
+### Pre-save transform tests
+###
+
+!! test
+pre-save transform: subst:
+!! options
+pst
!! wikitext
{{subst:test}}
!! html/php
c<nowiki />d
e<nowiki/ >f
-!! html
-<p><span typeof="mw:Nowiki"><div>[[foo]]</span></p>
-<p>ab</p>
-<p>cd</p>
-<p>ef</p>
+!! html/php+tidy
+<p><div>[[foo]]
+</p><p>a<nowiki / >b
+</p><p>cd
+</p><p>e<nowiki/ >f
+</p>
+!! html/parsoid
+<p><span typeof="mw:Nowiki"><div>[[foo]]</span></p>
+
+<p>a<nowiki / >b</p>
+
+<p>c<span typeof="mw:Nowiki"></span>d</p>
+
+<p>e<nowiki/ >f</p>
!! end
!! test
parsoid=wt2html
!! wikitext
<noWikI ><div>[[foo]]</Nowiki >
-!! html
+!! html/php+tidy
+<p><div>[[foo]]
+</p>
+!! html/parsoid
<p><span typeof="mw:Nowiki"><div>[[foo]]</span></p>
!! end
</p>
!! html/parsoid
<p>123<figure-inline class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><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>456</p>
-<p>123</p><figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><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><p>456</p>
-<p>123</p><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a></figure><p>456</p>
+<p>123</p><figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><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><p>456
+123</p><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a></figure><p>456</p>
!! end
!! test
<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|''bold template''}}."}]}' data-mw='{"attribs":[["thumbnail",{"html":"thumb"}],["alt",{"html":"alt=This is a <a rel=\"mw:WikiLink\" href=\"./Link\" title=\"Link\" data-parsoid='{\"stx\":\"simple\",\"a\":{\"href\":\"./Link\"},\"sa\":{\"href\":\"link\"},\"dsr\":[65,73,2,2]}'>link</a> and a <i about=\"#mwt1\" typeof=\"mw:Transclusion\" data-parsoid='{\"dsr\":[80,106,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&apos;&apos;bold template&apos;&apos;\"}},\"i\":0}}]}'>bold template</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|''bold template''}}.","resource":"Image:Foobar.jpg"}}'/></a><figcaption>This is the image caption</figcaption></figure>
!! end
+!! test
+Ampersand in alt attribute (T206940)
+!! options
+parsoid = {
+ "nativeGallery": true
+}
+!! wikitext
+[[File:Foobar.jpg|alt=&amp;]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|alt=&amp;
+</gallery>
+!! html/php+tidy
+<p><a href="/wiki/File:Foobar.jpg" class="image"><img alt="&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;" 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;" 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;" 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=''x''"},{"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=''x''","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=''x''|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="''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=<nowiki>''</nowiki>x<nowiki>''</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":"''x''","resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"alt":"alt=<nowiki>''</nowiki>x<nowiki>''</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=<nowiki>''</nowiki>x<nowiki>''</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)
+!! options
+parsoid = {
+ "nativeGallery": true
+}
+!! 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="''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-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 & 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 & 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; bar"}]}'><a href="./Foo_&_bar" data-parsoid='{"a":{"href":"./Foo_&_bar"},"sa":{"href":"link=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":{"extsrc":"\nFile:Foobar.jpg|link=Foo &amp; bar\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="./Foo_&_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)
+!! options
+parsoid = {
+ "nativeGallery": true
+}
+!! 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 & 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_&_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_&_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''s bar''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''s bar''s"},{"ck":"caption","ak":"caption1"}]}' data-mw='{"caption":"caption1"}'><a href="./Foos_bars" data-parsoid='{"a":{"href":"./Foos_bars"},"sa":{"href":"link=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" 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=''Main Page''"},{"ck":"caption","ak":"caption2"}]}' data-mw='{"caption":"caption2"}'><a href="./Main_Page" data-parsoid='{"a":{"href":"./Main_Page"},"sa":{"href":"link=''Main Page''"}}'><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''s bar''s|caption1\nFile:Foobar.jpg|link=''Main Page''|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<nowiki>''</nowiki>s_bar<nowiki>''</nowiki>s"},{"ck":"caption","ak":"caption"}]}' data-mw='{"caption":"caption"}'><a href="./Foo''s_bar''s" data-parsoid='{"a":{"href":"./Foo''s_bar''s"},"sa":{"href":"link=Foo<nowiki>''</nowiki>s_bar<nowiki>''</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<nowiki>''</nowiki>s_bar<nowiki>''</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)
+!! options
+parsoid = {
+ "nativeGallery": true
+}
+!! 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
+HTML entity prefix in link markup (T209236)
+!! wikitext
+[[File:Foobar.jpg|link=https://example.com?foo¶ms=bar]]
+
+<!-- consistency with gallery extension -->
+<gallery>
+File:Foobar.jpg|link=https://example.com?foo¶ms=bar
+</gallery>
+!! html/php+tidy
+<p><a href="https://example.com?foo&params=bar" rel="nofollow"><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="https://example.com?foo&params=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="https://example.com?foo&params=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=https://example.com?foo&params=bar\n"}}'>
+<li class="gallerybox">
+<div class="thumb"><figure-inline typeof="mw:Image"><a href="https://example.com?foo&params=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
Image with table with attributes in caption
!! options
</figcaption></figure>
!! end
-###################
-# Conflicting image format options.
-# First option specified should 'win'.
-# All three cases in each test should be identical.
-
!! test
-Image with 'frameless' first.
+Image with heading and horizontal rule in caption
+!! wikitext
+[[File:Foobar.jpg|thumb|
+===Testing===
+123
+--------------
+]]
+!! html/php
+<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><h3><span class="mw-headline" id="Testing">Testing</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: Testing">edit</a><span class="mw-editsection-bracket">]</span></span></h3> 123 <hr /></div></div></div>
+
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"\n=== Testing ===\n123\n--------------\n"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{"href":"File:Foobar.jpg"}}'><img 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":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>
+<h3 id="Testing">Testing</h3>
+123
+<hr data-parsoid='{"extra_dashes":10}'/>
+</figcaption></figure>
+!! end
+
+###################
+# Conflicting image format options.
+# First option specified should 'win'.
+# All three cases in each test should be identical.
+
+!! test
+Image with 'frameless' first.
!! options
parsoid=wt2html,wt2wt,html2html
!! wikitext
<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.svg"><img resource="./File:Foobar.svg" src="//example.com/images/thumb/f/ff/Foobar.svg/220px-Foobar.svg.png" data-file-width="240" data-file-height="180" data-file-type="drawing" height="165" width="220"/></a><figcaption>lang=invalid:language:code</figcaption></figure>
!! end
+!! test
+SVG thumbnails in page language
+!! options
+language=ru
+wgMediaInTargetLanguage = true
+!! wikitext
+[[File:Foobar.svg]] [[File:Foobar.svg|lang=en]]
+!! html/php
+<p><a href="/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/langru-240px-Foobar.svg.png" width="240" height="180" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langru-360px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langru-480px-Foobar.svg.png 2x" /></a> <a href="/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Foobar.svg&lang=en" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/240px-Foobar.svg.png" width="240" height="180" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/480px-Foobar.svg.png 2x" /></a>
+</p>
+!! end
+
+!! test
+SVG thumbnails in page language not present in the file
+!! options
+language=de
+wgMediaInTargetLanguage = true
+!! wikitext
+[[File:Foobar.svg]] [[File:Foobar.svg|lang=ru]]
+!! html/php
+<p><a href="/wiki/Datei:Foobar.svg" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/240px-Foobar.svg.png" width="240" height="180" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/360px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/480px-Foobar.svg.png 2x" /></a> <a href="/index.php?title=Datei:Foobar.svg&lang=ru" class="image"><img alt="Foobar.svg" src="http://example.com/images/thumb/f/ff/Foobar.svg/langru-240px-Foobar.svg.png" width="240" height="180" srcset="http://example.com/images/thumb/f/ff/Foobar.svg/langru-360px-Foobar.svg.png 1.5x, http://example.com/images/thumb/f/ff/Foobar.svg/langru-480px-Foobar.svg.png 2x" /></a>
+</p>
+!! end
+
!! test
T3887: A ISBN with a thumbnail
!! wikitext
<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>This is <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc12354">RFC 12354</a></div></div></div>
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>This is <a href="https://tools.ietf.org/html/rfc12354" rel="mw:ExtLink" class="external text">RFC 12354</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>This is <a href="https://tools.ietf.org/html/rfc12354" rel="mw:ExtLink" class="external mw-magiclink">RFC 12354</a></figcaption></figure>
!! end
!! test
<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption> bar</figcaption></figure>
!!end
+# html/php output not have newlines after table, td, th, etc. because
+# Linker::makeThumbLink2() replaces the newlines with spaces since
+# the table is inside a caption.
+# FIXME: Verify if that circa 2004 fix is still required.
!! test
Image: caption containing a table
!! options
!! wikitext
[[Image:Foobar.jpg|thumb|200px|This is an example image thumbnail caption with a table
{|
-! Foo !! Bar
+!Foo!!Bar
|-
-| Foo1 || Bar1
+|Foo1||Bar1
|}
and some more text.]]
!! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is an example image thumbnail caption with a table <table> <tr> <th> Foo </th> <th> Bar </th></tr> <tr> <td> Foo1 </td> <td> Bar1 </td></tr></table> and some more text.</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:202px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" width="200" height="23" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/400px-Foobar.jpg 2x" /></a> <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="Enlarge"></a></div>This is an example image thumbnail caption with a table <table> <tr> <th>Foo</th> <th>Bar </th></tr> <tr> <td>Foo1</td> <td>Bar1 </td></tr></table> and some more text.</div></div></div>
!! html/parsoid
<figure typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption>This is an example image thumbnail caption with a table
<table>
<tbody>
-<tr><th>Foo </th><th>Bar</th></tr>
+<tr><th>Foo</th><th>Bar</th></tr>
<tr>
-<td>Foo1 </td>
+<td>Foo1</td>
<td>Bar1</td></tr></tbody></table>and some more text.</figcaption></figure>
!! end
!! end
!! test
-Parsoid-specific image handling - simple image with size, middle alignment,
-non-standard namespace alias
+Parsoid-specific image handling - simple image with size, middle alignment, non-standard namespace alias
!! options
parsoid=wt2wt,wt2html,html2html
!! wikitext
!! end
!! test
-Parsoid-specific image handling - simple image with size and middle alignment
-(existing content)
+Parsoid-specific image handling - simple image with size and middle alignment (existing content)
!! wikitext
[[File:Foobar.jpg|50px|middle]]
!! html/parsoid
!! end
!! test
-Parsoid-specific image handling - simple image with size and middle alignment
-and non-standard namespace name
+Parsoid-specific image handling - simple image with size and middle alignment and non-standard namespace name
!! options
parsoid=wt2html,wt2wt,html2html
!! wikitext
!! test
Parsoid-specific image handling - thumbnail with halign, valign, and caption
+!! options
+parsoid=wt2html,html2html
!! wikitext
[[File:Foobar.jpg|left|baseline|thumb|caption content]]
!! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>caption content</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>caption content</figcaption></figure>
!! end
!! test
-Parsoid-specific image handling - thumbnail with halign, valign, and caption
-(existing content)
+Parsoid-specific image handling - thumbnail with halign, valign, and caption (existing content)
+!! options
+parsoid=wt2html,html2html
!! wikitext
[[File:Foobar.jpg|thumb|left|baseline|caption content]]
!! html/parsoid
-<figure class="mw-default-size mw-halign-left mw-valign-baseline" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img 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":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
+<figure class="mw-default-size mw-halign-left" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"left","ak":"left"},{"ck":"baseline","ak":"baseline"},{"ck":"caption","ak":"caption content"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img 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":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption content</figcaption></figure>
!! end
!! test
Parsoid-specific image handling - thumbnail with specific size, halign, valign, and caption
+!! options
+parsoid=wt2html,html2html
!! wikitext
[[Image:Foobar.jpg|right|middle|thumb|50x50px|caption]]
!! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50"/></a><figcaption>caption</figcaption></figure>
!! end
!! test
-Parsoid-specific image handling - thumbnail with specific size, halign,
-valign, and caption (existing content)
+Parsoid-specific image handling - thumbnail with specific size, halign, valign, and caption (existing content)
+!! options
+parsoid=wt2html,html2html
!! wikitext
[[File:Foobar.jpg|thumb|50x50px|right|middle|caption]]
!! html/parsoid
-<figure class="mw-halign-right mw-valign-middle" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-right" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"width","ak":"50x50px"},{"ck":"right","ak":"right"},{"ck":"middle","ak":"middle"},{"ck":"caption","ak":"caption"}],"size":"50x50"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="6" width="50" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"6","width":"50"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>caption</figcaption></figure>
!! end
!! test
-Parsoid-specific image handling - framed image with specific size and caption
-(size is ignored)
+Parsoid-specific image handling - framed image with specific size and caption (size is ignored)
!! options
parsoid=wt2html,wt2wt,html2html
!! wikitext
!! end
!! test
-Parsoid-specific image handling - framed image with specific size, halign, valign, and caption
-(size is ignored)
+Parsoid-specific image handling - framed image with specific size, halign, valign, and caption (size is ignored)
!! options
-parsoid=wt2html,wt2wt,html2html
+parsoid=wt2html,html2html
!! wikitext
[[File:Foobar.jpg|left|baseline|frame|500x50px|caption]]
!! html/parsoid
-<figure class="mw-halign-left mw-valign-baseline" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><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><figcaption>caption</figcaption></figure>
+<figure class="mw-halign-left" typeof="mw:Image/Frame"><a href="./File:Foobar.jpg"><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><figcaption>caption</figcaption></figure>
!! end
!! test
<references />
!! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption with templated ref: {{echo|<ref>foo</ref>}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img 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":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption with templated ref: <sup about="#mwt5" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<ref>foo</ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption with templated ref: {{echo|<ref>foo</ref>}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img 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":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption with templated ref: <sup about="#mwt5" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<ref>foo</ref>"}},"i":0}}]}'><a href="./Parser_test#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></sup></figcaption></figure>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Parser_test#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
!! end
!! test
<references />
!! html/parsoid
-<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: <ref>foo</ref>"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: <sup about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid='{\"dsr\":[64,78,5,6]}' data-mw='{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-1\"},\"attrs\":{}}'><a href=\"./Main_Page#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\"><span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]</span></a></sup>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{"href":"File:Foobar.jpg"}}'><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":"caption","ak":"Undisplayed caption in inline image with ref: <ref>foo</ref>"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: <sup about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid='{\"dsr\":[64,78,5,6]}' data-mw='{\"name\":\"ref\",\"attrs\":{},\"body\":{\"id\":\"mw-reference-text-cite_note-1\"}}'><a href=\"./Parser_test#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\"><span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]</span></a></sup>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{"href":"File:Foobar.jpg"}}'><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>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Parser_test#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
!! end
!! test
<references />
!! html/parsoid
-<p><figure-inline class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: {{echo|<ref>{{echo|foo}}</ref>}}"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: <sup about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Transclusion mw:Extension/ref\" data-parsoid='{\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;ref>{{echo|foo}}&lt;/ref>\"}},\"i\":0}}]}'><a href=\"./Main_Page#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\"><span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]</span></a></sup>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{"href":"File:Foobar.jpg"}}'><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":"caption","ak":"Undisplayed caption in inline image with ref: {{echo|<ref>{{echo|foo}}</ref>}}"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: <sup about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Transclusion mw:Extension/ref\" data-parsoid='{\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&lt;ref>{{echo|foo}}&lt;/ref>\"}},\"i\":0}}]}'><a href=\"./Parser_test#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\"><span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]</span></a></sup>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{"href":"File:Foobar.jpg"}}'><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>
-<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+<ol class="mw-references references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Parser_test#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
!! end
###
* 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
!! test
3. Categories and newlines: newline suppression for last list item should RT properly
!! wikitext
-* a
-* b
+*a
+*b
[[Category:Foo]]
[[Category:Bar]]
[[Category:Baz]]
+
+:c
+
+[[Category:C]]
+
+;d
+
+[[Category:D]]
!! html/parsoid
-<ul><li> a</li>
-<li> b</li></ul>
+<ul><li>a</li>
+<li>b</li></ul>
-<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/>
+<link rel="mw:PageProp/Category" href="./Category:Foo"/>
-<link rel="mw:PageProp/Category" href="./Category:Bar" data-parsoid='{"stx":"simple","a":{"href":"./Category:Bar"},"sa":{"href":"Category:Bar"}}'/>
-<link rel="mw:PageProp/Category" href="./Category:Baz" data-parsoid='{"stx":"simple","a":{"href":"./Category:Baz"},"sa":{"href":"Category:Baz"}}'/>
+<link rel="mw:PageProp/Category" href="./Category:Bar"/>
+<link rel="mw:PageProp/Category" href="./Category:Baz"/>
+
+<dl><dd>c</dd></dl>
+
+<link rel="mw:PageProp/Category" href="./Category:C"/>
+
+<dl><dt>d</dt></dl>
+
+<link rel="mw:PageProp/Category" href="./Category:D"/>
!! end
!! test
4. Categories and newlines: newline suppression for last list item should RT properly
!! wikitext
-* a
-**** b
+*a
+****b
[[Category:Foo]]
!! html/parsoid
-<ul><li> a
-<ul><li><ul><li><ul><li> b</li></ul></li></ul></li></ul></li></ul>
+<ul><li>a
+<ul><li><ul><li><ul><li>b</li></ul></li></ul></li></ul></li></ul>
<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/>
!! end
!! options
parsoid=wt2html
!! wikitext
-* a
-** b
+*a
+**b
[[Category:Foo]]
-* c
-** d
+*c
+**d
[[Category:Foo]]
!! html/parsoid
-<ul><li> a
-<ul><li> b
+<ul><li>a
+<ul><li>b
<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/></li></ul></li>
-<li> c
-<ul><li> d</li></ul></li></ul>
+<li>c
+<ul><li>d</li></ul></li></ul>
<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/>
!! end
!! options
parsoid=wt2html
!! wikitext
-* a [[Category:Foo]]
+*a [[Category:Foo]]
!! html/parsoid
-<ul><li>a <link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/></li></ul>
+<ul><li>a<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/></li></ul>
!! end
# This test also demonstrates because of newline+category tunneling
!! test
7. Categories and newlines: migrateTrailingCategories dom pass should leave template content alone
!! wikitext
-* {{echo|a
+*{{echo|a
[[Category:Foo]]}}
!! html/parsoid
-<ul><li> <span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n[[Category:Foo]]"}},"i":0}}]}'>a
+<ul><li><span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n[[Category:Foo]]"}},"i":0}}]}'>a
</span><link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"}}'/></li></ul>
!! end
!! test
8. Categories and newlines: migrateTrailingCategories dom pass should not get tripped by intervening templates
!! wikitext
-* a
+*a
{{echo|[[Category:Foo]]
[[Category:Bar]]}}
[[Category:Baz]]
!! html/parsoid
-<ul><li> a</li></ul>
+<ul><li>a</li></ul>
<link rel="mw:PageProp/Category" href="./Category:Foo" about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"simple","a":{"href":"./Category:Foo"},"sa":{"href":"Category:Foo"},"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[Category:Foo]]\n[[Category:Bar]]"}},"i":0}}]}'/><span about="#mwt1">
</span><link rel="mw:PageProp/Category" href="./Category:Bar" about="#mwt1" data-parsoid='{"stx":"simple","a":{"href":"./Category:Bar"},"sa":{"href":"Category:Bar"}}'/>
!! end
!! test
-9. Categories and newlines: should behave properly with linkprefix (T87753)
+Categories and newlines: migrateTrailingCategories dom pass should not get tripped by comments and whitespace
+!! wikitext
+*a
+
+[[Category:Bar]]<!--boo1--> <!--boo2-->
+[[Category:Baz]]<!--boo3--> <!--boo4-->
+!! html/parsoid
+<ul><li>a</li></ul>
+
+<link rel="mw:PageProp/Category" href="./Category:Bar"/><!--boo1--> <!--boo2-->
+<link rel="mw:PageProp/Category" href="./Category:Baz"/><!--boo3--> <!--boo4-->
+!! end
+
+!! test
+Categories and newlines: should behave properly with linkprefix (T87753)
!! options
language=ar
!! wikitext
!! end
!! test
-10. No regressions on internal links following category (T174639)
+No regressions on internal links following category (T174639)
!! options
parsoid=wt2html,html2html
!! wikitext
!! 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&action=edit&redlink=1" class="new" title="Category:Foo (page does not exist)">Category:Foo</a>
+<a href="/index.php?title=Category:Foo&action=edit&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>
!! 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&action=edit&redlink=1" class="new" title="File:Foo.png (page does not exist)">File:Foo.png</a>
+<a href="/index.php?title=File:Foo.png&action=edit&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>
!! 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
!! test
Basic section headings
!! wikitext
-== Headline 1 ==
+==Headline 1==
Some text
==Headline 2==
!! test
Section headings with TOC
!! wikitext
-== Headline 1 ==
-=== Subheadline 1 ===
-===== Skipping a level =====
-====== Skipping a level ======
+==Headline 1==
+===Subheadline 1===
+=====Skipping a level=====
+======Skipping a level======
-== Headline 2 ==
+==Headline 2==
Some text
===Another headline===
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Headline_1"><span class="tocnumber">1</span> <span class="toctext">Headline 1</span></a>
<ul>
TOC anchors don't collide
!! wikitext
__FORCETOC__
-== Headline 2 ==
-== Headline ==
-== Headline 2 ==
-== Headline ==
+==Headline 2==
+==Headline==
+==Headline 2==
+==Headline==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Headline_2"><span class="tocnumber">1</span> <span class="toctext">Headline 2</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#Headline"><span class="tocnumber">2</span> <span class="toctext">Headline</span></a></li>
!! options
parsoid=wt2html
!! wikitext
-= Level 1 Heading=
-== Level 2 Heading==
-=== Level 3 Heading===
-==== Level 4 Heading====
-===== Level 5 Heading=====
-====== Level 6 Heading======
-======= Level 7 Heading=======
-======== Level 8 Heading========
-========= Level 9 Heading=========
-========== Level 10 Heading==========
-!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+=Level 1 Heading=
+==Level 2 Heading==
+===Level 3 Heading===
+====Level 4 Heading====
+=====Level 5 Heading=====
+======Level 6 Heading======
+=======Level 7 Heading=======
+========Level 8 Heading========
+=========Level 9 Heading=========
+==========Level 10 Heading==========
+!! 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="#Level_1_Heading"><span class="tocnumber">1</span> <span class="toctext">Level 1 Heading</span></a>
<ul>
<li class="toclevel-5 tocsection-5"><a href="#Level_5_Heading"><span class="tocnumber">1.1.1.1.1</span> <span class="toctext">Level 5 Heading</span></a>
<ul>
<li class="toclevel-6 tocsection-6"><a href="#Level_6_Heading"><span class="tocnumber">1.1.1.1.1.1</span> <span class="toctext">Level 6 Heading</span></a></li>
-<li class="toclevel-6 tocsection-7"><a href="#.3D_Level_7_Heading.3D"><span class="tocnumber">1.1.1.1.1.2</span> <span class="toctext">= Level 7 Heading=</span></a></li>
-<li class="toclevel-6 tocsection-8"><a href="#.3D.3D_Level_8_Heading.3D.3D"><span class="tocnumber">1.1.1.1.1.3</span> <span class="toctext">== Level 8 Heading==</span></a></li>
-<li class="toclevel-6 tocsection-9"><a href="#.3D.3D.3D_Level_9_Heading.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.4</span> <span class="toctext">=== Level 9 Heading===</span></a></li>
-<li class="toclevel-6 tocsection-10"><a href="#.3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.5</span> <span class="toctext">==== Level 10 Heading====</span></a></li>
+<li class="toclevel-6 tocsection-7"><a href="#.3DLevel_7_Heading.3D"><span class="tocnumber">1.1.1.1.1.2</span> <span class="toctext">=Level 7 Heading=</span></a></li>
+<li class="toclevel-6 tocsection-8"><a href="#.3D.3DLevel_8_Heading.3D.3D"><span class="tocnumber">1.1.1.1.1.3</span> <span class="toctext">==Level 8 Heading==</span></a></li>
+<li class="toclevel-6 tocsection-9"><a href="#.3D.3D.3DLevel_9_Heading.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.4</span> <span class="toctext">===Level 9 Heading===</span></a></li>
+<li class="toclevel-6 tocsection-10"><a href="#.3D.3D.3D.3DLevel_10_Heading.3D.3D.3D.3D"><span class="tocnumber">1.1.1.1.1.5</span> <span class="toctext">====Level 10 Heading====</span></a></li>
</ul>
</li>
</ul>
<h4><span class="mw-headline" id="Level_4_Heading">Level 4 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=4" title="Edit section: Level 4 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h4>
<h5><span class="mw-headline" id="Level_5_Heading">Level 5 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=5" title="Edit section: Level 5 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h5>
<h6><span class="mw-headline" id="Level_6_Heading">Level 6 Heading</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=6" title="Edit section: Level 6 Heading">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
-<h6><span class="mw-headline" id=".3D_Level_7_Heading.3D">= Level 7 Heading=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=7" title="Edit section: = Level 7 Heading=">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
-<h6><span class="mw-headline" id=".3D.3D_Level_8_Heading.3D.3D">== Level 8 Heading==</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=8" title="Edit section: == Level 8 Heading==">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
-<h6><span class="mw-headline" id=".3D.3D.3D_Level_9_Heading.3D.3D.3D">=== Level 9 Heading===</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=9" title="Edit section: === Level 9 Heading===">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
-<h6><span class="mw-headline" id=".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D">==== Level 10 Heading====</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=10" title="Edit section: ==== Level 10 Heading====">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
+<h6><span class="mw-headline" id=".3DLevel_7_Heading.3D">=Level 7 Heading=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=7" title="Edit section: =Level 7 Heading=">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
+<h6><span class="mw-headline" id=".3D.3DLevel_8_Heading.3D.3D">==Level 8 Heading==</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=8" title="Edit section: ==Level 8 Heading==">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
+<h6><span class="mw-headline" id=".3D.3D.3DLevel_9_Heading.3D.3D.3D">===Level 9 Heading===</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=9" title="Edit section: ===Level 9 Heading===">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
+<h6><span class="mw-headline" id=".3D.3D.3D.3DLevel_10_Heading.3D.3D.3D.3D">====Level 10 Heading====</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=10" title="Edit section: ====Level 10 Heading====">edit</a><span class="mw-editsection-bracket">]</span></span></h6>
!! html/parsoid
-<h1 id="Level_1_Heading" data-parsoid='{}'> Level 1 Heading</h1>
-<h2 id="Level_2_Heading" data-parsoid='{}'> Level 2 Heading</h2>
-<h3 id="Level_3_Heading" data-parsoid='{}'> Level 3 Heading</h3>
-<h4 id="Level_4_Heading" data-parsoid='{}'> Level 4 Heading</h4>
-<h5 id="Level_5_Heading" data-parsoid='{}'> Level 5 Heading</h5>
-<h6 id="Level_6_Heading" data-parsoid='{}'> Level 6 Heading</h6>
-<h6 id="=_Level_7_Heading=" data-parsoid='{}'><span id=".3D_Level_7_Heading.3D" typeof="mw:FallbackId"></span>= Level 7 Heading=</h6>
-<h6 id="==_Level_8_Heading==" data-parsoid='{}'><span id=".3D.3D_Level_8_Heading.3D.3D" typeof="mw:FallbackId"></span>== Level 8 Heading==</h6>
-<h6 id="===_Level_9_Heading===" data-parsoid='{}'><span id=".3D.3D.3D_Level_9_Heading.3D.3D.3D" typeof="mw:FallbackId"></span>=== Level 9 Heading===</h6>
-<h6 id="====_Level_10_Heading====" data-parsoid='{}'><span id=".3D.3D.3D.3D_Level_10_Heading.3D.3D.3D.3D" typeof="mw:FallbackId"></span>==== Level 10 Heading====</h6>
+<h1 id="Level_1_Heading" data-parsoid='{}'>Level 1 Heading</h1>
+<h2 id="Level_2_Heading" data-parsoid='{}'>Level 2 Heading</h2>
+<h3 id="Level_3_Heading" data-parsoid='{}'>Level 3 Heading</h3>
+<h4 id="Level_4_Heading" data-parsoid='{}'>Level 4 Heading</h4>
+<h5 id="Level_5_Heading" data-parsoid='{}'>Level 5 Heading</h5>
+<h6 id="Level_6_Heading" data-parsoid='{}'>Level 6 Heading</h6>
+<h6 id="=Level_7_Heading=" data-parsoid='{}'><span id=".3DLevel_7_Heading.3D" typeof="mw:FallbackId"></span>=Level 7 Heading=</h6>
+<h6 id="==Level_8_Heading==" data-parsoid='{}'><span id=".3D.3DLevel_8_Heading.3D.3D" typeof="mw:FallbackId"></span>==Level 8 Heading==</h6>
+<h6 id="===Level_9_Heading===" data-parsoid='{}'><span id=".3D.3D.3DLevel_9_Heading.3D.3D.3D" typeof="mw:FallbackId"></span>===Level 9 Heading===</h6>
+<h6 id="====Level_10_Heading====" data-parsoid='{}'><span id=".3D.3D.3D.3DLevel_10_Heading.3D.3D.3D.3D" typeof="mw:FallbackId"></span>====Level 10 Heading====</h6>
!! end
!! test
TOC regression (T11764)
!! wikitext
-== title 1 ==
-=== title 1.1 ===
-==== title 1.1.1 ====
-=== title 1.2 ===
-== title 2 ==
-=== title 2.1 ===
+==title 1==
+===title 1.1===
+====title 1.1.1====
+===title 1.2===
+==title 2==
+===title 2.1===
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
<ul>
__FORCETOC__
==<span id="old-anchor"></span>New title==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#New_title"><span class="tocnumber">1</span> <span class="toctext">New title</span></a></li>
</ul>
!! options
wgMaxTocLevel=3
!! wikitext
-== title 1 ==
-=== title 1.1 ===
-==== title 1.1.1 ====
-=== title 1.2 ===
-== title 2 ==
-=== title 2.1 ===
+==title 1==
+===title 1.1===
+====title 1.1.1====
+===title 1.2===
+==title 2==
+===title 2.1===
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
<ul>
====Section 1.1.1.1====
==Section 2==
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Section_1"><span class="tocnumber">1</span> <span class="toctext">Section 1</span></a>
<ul>
!! test
Resolving duplicate section names
!! wikitext
-== Foo bar ==
-== Foo bar ==
+==Foo bar==
+==Foo bar==
!! html
<h2><span class="mw-headline" id="Foo_bar">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<h2><span class="mw-headline" id="Foo_bar_2">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! test
Resolving duplicate section names with differing case (T12721)
!! wikitext
-== Foo bar ==
-== Foo Bar ==
+==Foo bar==
+==Foo Bar==
!! html
<h2><span class="mw-headline" id="Foo_bar">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<h2><span class="mw-headline" id="Foo_Bar_2">Foo Bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
TOC regression (T14077)
!! wikitext
__TOC__
-== title 1 ==
-=== title 1.1 ===
-== title 2 ==
+==title 1==
+===title 1.1===
+==title 2==
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#title_1"><span class="tocnumber">1</span> <span class="toctext">title 1</span></a>
<ul>
!! wikitext
The tooltips shall not show entities to the user (ie. be double escaped)
-== text > text ==
+==text > text==
section 1
-== text < text ==
+==text < text==
section 2
-== text & text ==
+==text & text==
section 3
-== text ' text ==
+==text ' text==
section 4
-== text " text ==
+==text " text==
section 5
!! html/php
<p>The tooltips shall not show entities to the user (ie. be double escaped)
</p>
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#text_.3E_text"><span class="tocnumber">1</span> <span class="toctext">text > text</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#text_.3C_text"><span class="tocnumber">2</span> <span class="toctext">text < text</span></a></li>
!! html/parsoid
<p>The tooltips shall not show entities to the user (ie. be double escaped)</p>
-<h2 id="text_>_text"><span id="text_.3E_text" typeof="mw:FallbackId"></span> text > text </h2>
+<h2 id="text_>_text"><span id="text_.3E_text" typeof="mw:FallbackId"></span>text > text</h2>
<p>section 1</p>
-<h2 id="text_<_text"><span id="text_.3C_text" typeof="mw:FallbackId"></span> text < text </h2>
+<h2 id="text_<_text"><span id="text_.3C_text" typeof="mw:FallbackId"></span>text < text</h2>
<p>section 2</p>
-<h2 id="text_&_text"><span id="text_.26_text" typeof="mw:FallbackId"></span> text & text </h2>
+<h2 id="text_&_text"><span id="text_.26_text" typeof="mw:FallbackId"></span>text & text</h2>
<p>section 3</p>
-<h2 id="text_'_text"><span id="text_.27_text" typeof="mw:FallbackId"></span> text ' text </h2>
+<h2 id="text_'_text"><span id="text_.27_text" typeof="mw:FallbackId"></span>text ' text</h2>
<p>section 4</p>
-<h2 id='text_"_text'><span id="text_.22_text" typeof="mw:FallbackId"></span> text " text </h2>
+<h2 id='text_"_text'><span id="text_.22_text" typeof="mw:FallbackId"></span>text " text</h2>
<p>section 5</p>
!! end
!! wikitext
Id should not contain + for spaces
-== Space between Text ==
+==Space between Text==
section 1
-== Space-Entity between Text ==
+==Space-Entity between Text==
section 2
-== Plus+between+Text ==
+==Plus+between+Text==
section 3
-== Plus-Entity+between+Text ==
+==Plus-Entity+between+Text==
section 4
-== Underscore_between_Text ==
+==Underscore_between_Text==
section 5
-== Underscore-Entity_between_Text ==
+==Underscore-Entity_between_Text==
section 6
[[#Space between Text]]
!! html/php
<p>Id should not contain + for spaces
</p>
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Space_between_Text"><span class="tocnumber">1</span> <span class="toctext">Space between Text</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#Space-Entity_between_Text"><span class="tocnumber">2</span> <span class="toctext">Space-Entity between Text</span></a></li>
!! html/parsoid
<p>Id should not contain + for spaces</p>
-<h2 id="Space_between_Text"> Space between Text </h2>
+<h2 id="Space_between_Text">Space between Text</h2>
<p>section 1</p>
-<h2 id="Space-Entity_between_Text"> Space-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#32;","srcContent":" "}'> </span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#32;","srcContent":" "}'> </span>Text </h2>
+<h2 id="Space-Entity_between_Text">Space-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#32;","srcContent":" "}'> </span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#32;","srcContent":" "}'> </span>Text</h2>
<p>section 2</p>
-<h2 id="Plus+between+Text"><span id="Plus.2Bbetween.2BText" typeof="mw:FallbackId"></span> Plus+between+Text </h2>
+<h2 id="Plus+between+Text"><span id="Plus.2Bbetween.2BText" typeof="mw:FallbackId"></span>Plus+between+Text</h2>
<p>section 3</p>
-<h2 id="Plus-Entity+between+Text"><span id="Plus-Entity.2Bbetween.2BText" typeof="mw:FallbackId"></span> Plus-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#43;","srcContent":"+"}'>+</span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#43;","srcContent":"+"}'>+</span>Text </h2>
+<h2 id="Plus-Entity+between+Text"><span id="Plus-Entity.2Bbetween.2BText" typeof="mw:FallbackId"></span>Plus-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#43;","srcContent":"+"}'>+</span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#43;","srcContent":"+"}'>+</span>Text</h2>
<p>section 4</p>
-<h2 id="Underscore_between_Text"> Underscore_between_Text </h2>
+<h2 id="Underscore_between_Text">Underscore_between_Text</h2>
<p>section 5</p>
-<h2 id="Underscore-Entity_between_Text"> Underscore-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#95;","srcContent":"_"}'>_</span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#95;","srcContent":"_"}'>_</span>Text </h2>
+<h2 id="Underscore-Entity_between_Text">Underscore-Entity<span typeof="mw:Entity" data-parsoid='{"src":"&#95;","srcContent":"_"}'>_</span>between<span typeof="mw:Entity" data-parsoid='{"src":"&#95;","srcContent":"_"}'>_</span>Text</h2>
<p>section 6</p>
-<p><a rel="mw:WikiLink" href="./Main_Page#Space_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Space_between_Text"},"sa":{"href":"#Space between Text"}}'>#Space between Text</a>
-<a rel="mw:WikiLink" href="./Main_Page#Space-Entity_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Space-Entity_between_Text"},"sa":{"href":"#Space-Entity&#32;between&#32;Text"}}'>#Space-Entity between Text</a>
-<a rel="mw:WikiLink" href="./Main_Page#Plus+between+Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Plus+between+Text"},"sa":{"href":"#Plus+between+Text"}}'>#Plus+between+Text</a>
-<a rel="mw:WikiLink" href="./Main_Page#Plus-Entity+between+Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Plus-Entity+between+Text"},"sa":{"href":"#Plus-Entity&#43;between&#43;Text"}}'>#Plus-Entity+between+Text</a>
-<a rel="mw:WikiLink" href="./Main_Page#Underscore_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Underscore_between_Text"},"sa":{"href":"#Underscore_between_Text"}}'>#Underscore_between_Text</a>
-<a rel="mw:WikiLink" href="./Main_Page#Underscore-Entity_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Underscore-Entity_between_Text"},"sa":{"href":"#Underscore-Entity&#95;between&#95;Text"}}'>#Underscore-Entity_between_Text</a></p>
+<p><a rel="mw:WikiLink" href="./Parser_test#Space_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Space_between_Text"},"sa":{"href":"#Space between Text"}}'>#Space between Text</a>
+<a rel="mw:WikiLink" href="./Parser_test#Space-Entity_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Space-Entity_between_Text"},"sa":{"href":"#Space-Entity&#32;between&#32;Text"}}'>#Space-Entity between Text</a>
+<a rel="mw:WikiLink" href="./Parser_test#Plus+between+Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Plus+between+Text"},"sa":{"href":"#Plus+between+Text"}}'>#Plus+between+Text</a>
+<a rel="mw:WikiLink" href="./Parser_test#Plus-Entity+between+Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Plus-Entity+between+Text"},"sa":{"href":"#Plus-Entity&#43;between&#43;Text"}}'>#Plus-Entity+between+Text</a>
+<a rel="mw:WikiLink" href="./Parser_test#Underscore_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Underscore_between_Text"},"sa":{"href":"#Underscore_between_Text"}}'>#Underscore_between_Text</a>
+<a rel="mw:WikiLink" href="./Parser_test#Underscore-Entity_between_Text" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Underscore-Entity_between_Text"},"sa":{"href":"#Underscore-Entity&#95;between&#95;Text"}}'>#Underscore-Entity_between_Text</a></p>
!! end
# Parsoid html2wt disabled because it adds padding spaces around =
=''italic'' heading==
==''italic'' heading=
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#foo.3D"><span class="tocnumber">1</span> <span class="toctext">foo=</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#.3Dfoo"><span class="tocnumber">2</span> <span class="toctext">=foo</span></a></li>
(__NOEDITSECTION__ for clearer output, doesn't matter here)
!! wikitext
<h1>Header 1</h1>
-== Header 1.1 ==
-== Header 1.2 ==
+==Header 1.1==
+==Header 1.2==
<h1>Header 2
</h1>
-== Header 2.1 ==
-== Header 2.2 ==
+==Header 2.1==
+==Header 2.2==
__NOEDITSECTION__
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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"><a href="#Header_1"><span class="tocnumber">1</span> <span class="toctext">Header 1</span></a>
<ul>
<h1><span class="mw-headline" id="Header_1">Header 1</span></h1>
<h2><span class="mw-headline" id="Header_1.1">Header 1.1</span></h2>
<h2><span class="mw-headline" id="Header_1.2">Header 1.2</span></h2>
-<h1><span class="mw-headline" id="Header_2">Header 2</span></h1>
+<h1><span class="mw-headline" id="Header_2">Header 2
+</span></h1>
<h2><span class="mw-headline" id="Header_2.1">Header 2.1</span></h2>
<h2><span class="mw-headline" id="Header_2.2">Header 2.2</span></h2>
!! html/parsoid
<h1 id="Header_1" data-parsoid='{"stx":"html"}'>Header 1</h1>
-<h2 id="Header_1.1" data-parsoid='{}'> Header 1.1 </h2>
-<h2 id="Header_1.2" data-parsoid='{}'> Header 1.2 </h2>
+<h2 id="Header_1.1" data-parsoid='{}'>Header 1.1</h2>
+<h2 id="Header_1.2" data-parsoid='{}'>Header 1.2</h2>
<h1 id="Header_2" data-parsoid='{"stx":"html"}'>Header 2
</h1>
-<h2 id="Header_2.1" data-parsoid='{}'> Header 2.1 </h2>
-<h2 id="Header_2.2" data-parsoid='{}'> Header 2.2 </h2>
+<h2 id="Header_2.1" data-parsoid='{}'>Header 2.1</h2>
+<h2 id="Header_2.2" data-parsoid='{}'>Header 2.2</h2>
<meta property="mw:PageProp/noeditsection"/>
!! end
parsoid=wt2html,html2html
!! wikitext
{| title= id=
-| hi
+|hi
|}
!! html/php
<table title="id=">
<tr>
-<td> hi
+<td>hi
</td></tr></table>
!! html/parsoid
<table title="id=">
-<tbody><tr><td> hi</td></tr>
+<tbody><tr><td>hi</td></tr>
</tbody></table>
!! end
Table multiple attributes correction
!! wikitext
{|
-!+ class="error" class="awesome"| status
+!+ class="error" class="awesome"|status
|}
!! html
<table>
<tr>
-<th class="awesome"> status
+<th class="awesome">status
</th></tr></table>
!!end
<a href="http://example.com/images/0/00/Video.ogv" class="internal" title="Video.ogv">Media:Video.ogv</a>
</p>
!! html/parsoid
-<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg">Media:Foobar.jpg</a>
-<a rel="mw:MediaLink" href="//example.com/images/0/00/Video.ogv" title="Video.ogv">Media:Video.ogv</a>
-<a rel="mw:MediaLink" href="//example.com/images/0/00/Video.ogv" title="Video.ogv" data-parsoid='{"a":{"namespace":"Media"},"sa":{"namespace":":Media"}}'>Media:Video.ogv</a></p>
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Media:Foobar.jpg" title="Foobar.jpg">Media:Foobar.jpg</a>
+<a rel="mw:MediaLink" href="//example.com/images/0/00/Video.ogv" resource="./Media:Video.ogv" title="Video.ogv">Media:Video.ogv</a>
+<a rel="mw:MediaLink" href="//example.com/images/0/00/Video.ogv" resource="./Media:Video.ogv" title="Video.ogv" data-parsoid='{"a":{"resource":"./Media:Video.ogv"},"sa":{"resource":":Media:Video.ogv"}}'>Media:Video.ogv</a></p>
!! end
!! test
<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">A neat file to look at</a>
</p>
!! html/parsoid
-<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg">A neat file to look at</a></p>
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Media:Foobar.jpg" title="Foobar.jpg">A neat file to look at</a></p>
+!! end
+
+!! test
+Localized media link
+!! options
+language=is
+!! wikitext
+[[Miðill:Foobar.jpg]]
+
+[[Miðill:Foobar.jpg|Icelandic]]
+!! html/php
+<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Miðill:Foobar.jpg</a>
+</p><p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Icelandic</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Miðill:Foobar.jpg" title="Foobar.jpg">Miðill:Foobar.jpg</a></p>
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Miðill:Foobar.jpg" title="Foobar.jpg">Icelandic</a></p>
!! end
# FIXME: this is still bad HTML tag nesting
# Parsoid & Remex fix the p-wrapping since they operate on the DOM.
!! test
Media link with nasty text
+!! options
+parsoid=wt2html,html2html
!! wikitext
[[Media:Foobar.jpg|Safe Link<div style=display:none>" onmouseover="alert(document.cookie)" onfoo="</div>]]
!! html/php
<a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link<div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div></a>
-!! html+php/tidy
-<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link</a></p>
-<div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div>
+!! html/php+tidy
+<p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg">Safe Link</a></p><a href="http://example.com/images/3/3a/Foobar.jpg" class="internal" title="Foobar.jpg"><div style="display:none">" onmouseover="alert(document.cookie)" onfoo="</div></a>
+!! html/parsoid
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Media:Foobar.jpg" title="Foobar.jpg">Safe Link</a></p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" resource="./Media:Foobar.jpg" title="Foobar.jpg"><div style="display:none" data-parsoid='{"stx":"html"}'>" onmouseover="alert(document.cookie)" onfoo="</div></a>
+!! end
+
+!! test
+Media link from missing resource (parsoid-only)
+!! options
+parsoid=html2wt
+!! html/parsoid
+<a rel="mw:MediaLink" href="http://example.com/images/3/3a/Foobar.jpg">Bat!</a>
+!! wikitext
+[[Media:Foobar.jpg|Bat!]]
+!! end
+
+!! test
+Media link from missing resource, localized (parsoid-only)
+!! options
+parsoid=html2wt
+language=is
+!! html/parsoid
+<a rel="mw:MediaLink" href="http://example.com/images/3/3a/Foobar.jpg">Bat!</a>
+!! wikitext
+[[Miðill:Foobar.jpg|Bat!]]
+!! end
+
+# This is a sanity test to ensure we don't crash or choke when given
+# old cached 1.7.0 HTML for media links; we don't require that the
+# result be "valid" because wt2wt was completely broken in 1.7.0
+!! test
+Media link from old 1.7.0 DOM spec (crash test, parsoid-only) T198511
+!! options
+parsoid=html2wt
!! html/parsoid
-<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg" data-parsoid='{"autoInsertedEnd":true}'>Safe Link</a></p><div style="display:none" data-parsoid='{"stx":"html"}'><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg" data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'>" onmouseover="alert(document.cookie)" onfoo="</a></div>
+<p>This is what Parsoid would emit (and we still handle this HTML fine):</p>
+<p><a rel="mw:MediaLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg">A neat file to look at</a></p>
+<p>But VisualEditor would mangle the rel attribute, and give us back this:</p>
+<p><a rel="mw:ExtLink" href="//example.com/images/3/3a/Foobar.jpg" title="Foobar.jpg">A neat file to look at</a></p>
+<p>But at least we don't crash when trying to handle the mangled HTML!</p>
+!! wikitext
+This is what Parsoid would emit (and we still handle this HTML fine):
+
+[[Media:Foobar.jpg|A neat file to look at]]
+
+But VisualEditor would mangle the rel attribute, and give us back this:
+
+[//example.com/images/3/3a/Foobar.jpg A neat file to look at]
+But at least we don't crash when trying to handle the mangled HTML!
!! end
!! test
<a href="/index.php?title=Special:Upload&wpDestFile=No_such_file.jpg" class="new" title="No such file.jpg">Media:No_such file.jpg</a>
</p>
!! html/parsoid
-<p><a rel="mw:MediaLink" href="./Special:FilePath/No_such.jpg" title="No such.jpg" typeof="mw:Error" data-mw='{"errors":[{"key":"apierror-filedoesnotexist","message":"This image does not exist."}]}' data-parsoid='{"a":{"fileName":"No_such.jpg"},"sa":{"fileName":"No such.jpg"}}'>Media:No such.jpg</a>
-<a rel="mw:MediaLink" href="./Special:FilePath/No_such_file.jpg" title="No such file.jpg" typeof="mw:Error" data-mw='{"errors":[{"key":"apierror-filedoesnotexist","message":"This image does not exist."}]}' data-parsoid='{"a":{"fileName":"No_such_file.jpg"},"sa":{"fileName":"No_such file.jpg"}}'>Media:No_such file.jpg</a></p>
+<p><a rel="mw:MediaLink" href="./Special:FilePath/No_such.jpg" resource="./Media:No_such.jpg" title="No such.jpg" typeof="mw:Error" data-mw='{"errors":[{"key":"apierror-filedoesnotexist","message":"This image does not exist."}]}' data-parsoid='{"a":{"resource":"./Media:No_such.jpg"},"sa":{"resource":"Media:No such.jpg"}}'>Media:No such.jpg</a>
+<a rel="mw:MediaLink" href="./Special:FilePath/No_such_file.jpg" resource="./Media:No_such_file.jpg" title="No such file.jpg" typeof="mw:Error" data-mw='{"errors":[{"key":"apierror-filedoesnotexist","message":"This image does not exist."}]}' data-parsoid='{"a":{"resource":"./Media:No_such_file.jpg"},"sa":{"resource":"Media:No_such file.jpg"}}'>Media:No_such file.jpg</a></p>
!! end
!! test
Table attribute legitimate extension
!! wikitext
{|
-!+ style="<nowiki>color:blue</nowiki>"| status
+!+ style="<nowiki>color:blue</nowiki>"|status
|}
!! html
<table>
<tr>
-<th style="color:blue"> status
+<th style="color:blue">status
</th></tr></table>
!!end
Table attribute safety
!! wikitext
{|
-!+ style="<nowiki>border-width:expression(0+alert(document.cookie))</nowiki>"| status
+!+ style="<nowiki>border-width:expression(0+alert(document.cookie))</nowiki>"|status
|}
!! html
<table>
<tr>
-<th style="/* insecure input */"> status
+<th style="/* insecure input */">status
</th></tr></table>
!! end
!! end
###
-### Parser hooks (see tests/parser/parserTestsParserHook.php for the <tag> extension)
+### Parser hooks (see tests/parser/ParserTestParserHook.php for the <tag> extension)
###
!! test
</pre>
!! html/parsoid
-<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{},"body":null}' data-parsoid='{}' about="#mwt2"></pre>
+<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{}}' data-parsoid='{}' about="#mwt2"></pre>
!! end
!! test
</pre>
!! html/parsoid
-<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{},"body":null}' data-parsoid='{}' about="#mwt2"></pre>
+<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{}}' data-parsoid='{}' about="#mwt2"></pre>
!! end
!! test
!! test
Parser hook: nested tags
+!! options
+parsoid=wt2html
!! wikitext
<tag><tag></tag></tag>
!! html/php
)
</pre></tag>
+!! html/php+tidy
+<pre>'<tag>'
+array (
+)
+</tag></pre><p></tag>
+</p>
!! html/parsoid
-<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{},"body":{"extsrc":"<tag>"}}' data-parsoid='{}' about="#mwt2"></pre></tag>
+<pre typeof="mw:Extension/tag" about="#mwt2" data-mw='{"name":"tag","attrs":{},"body":{"extsrc":"<tag>"}}'></pre><p></tag></p>
!! end
!! test
</pre>text
!! html/parsoid
-<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{"foo":"bar"},"body":null}' data-parsoid='{}' about="#mwt2"></pre>text
+<pre typeof="mw:Extension/tag" about="#mwt2" data-mw='{"name":"tag","attrs":{"foo":"bar"}}'></pre><p>text</p>
!! end
## </tag> should be output literally since there is no matching tag that begins it
</tag>
</p>
!! html/parsoid
-<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{"width":"200","height":"100","depth":"50","square":""},"body":null}' about="#mwt2"></pre><p>other stuff
+<pre typeof="mw:Extension/tag" data-mw='{"name":"tag","attrs":{"width":"200","height":"100","depth":"50","square":""}}' about="#mwt2"></pre><p>other stuff
</tag></p>
!! end
<p>this is a <b>test</b></p>
!! end
+!! test
+Parser hook: horizontal rule inside extension tag that outputs <pre>
+!! wikitext
+<tag>
+Hello
+<hr/>
+Goodbye
+</tag>
+!! html/php
+<pre>
+'
+Hello
+<hr/>
+Goodbye
+'
+array (
+)
+</pre>
+
+!! end
+
###
-### (see tests/parser/parserTestsParserHook.php for the <statictag> extension)
+### (see tests/parser/ParserTestParserHook.php for the <statictag> extension)
###
!! test
hello, world
</p>
!! html/parsoid
-<p><span typeof="mw:Extension/statictag" data-mw='{"name":"statictag","attrs":{},"body":{"extsrc":"hello, world"}}' data-parsoid='{}' about="#mwt2"></span></p>
-<p typeof="mw:Extension/statictag" data-mw='{"name":"statictag","attrs":{"action":"flush"},"body":null}' data-parsoid='{}' about="#mwt4">hello, world</p>
+<p><span typeof="mw:Extension/statictag" data-mw='{"name":"statictag","attrs":{},"body":{"extsrc":"hello, world"}}' about="#mwt2"></span></p>
+<p><span typeof="mw:Extension/statictag" data-mw='{"name":"statictag","attrs":{"action":"flush"}}' about="#mwt4">hello, world</span></p>
!! end
!! test
</p>
!! html/parsoid
<!-- <statictag>hello, world</statictag> -->
-<p typeof='mw:Extension/statictag' data-mw='{"name":"statictag","attrs":{"action":"flush"},"body":null}' data-parsoid='{}' about='#mwt2'></p>
+<p><span typeof='mw:Extension/statictag' data-mw='{"name":"statictag","attrs":{"action":"flush"}}' data-parsoid='{}' about='#mwt2'></span></p>
!! end
# Nested template calls; this case was broken by Parser.php rev 1.506,
### Sanitizer
###
-# Remex wraps empty tag runs with p-tags.
-# Parsoid strips them out during p-wrapping.
!! test
Sanitizer: Closing of open tags
!! wikitext
!! html/php+tidy
<p><s></s></p><table></table>
!! html/parsoid
-<s></s><table></table>
+<p><s data-parsoid='{"stx":"html"}'></s></p><table data-parsoid='{"stx":"html"}'></table>
!! end
!! test
parsoid=wt2html
!! wikitext
</s>
-!! html/php+tidy
+!! html+tidy
<p class="mw-empty-elt">
</p>
-!! html/parsoid
!! end
!! test
!! test
Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=""
+!! options
+title=[[Main Page]]
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
!! wikitext
<div style="width:50% ! important">important</div>
!! html
-<div style="width:50% ! important">important</div>
+<div style="width:50% ! important">important</div>
!!end
!! test
Fuzz testing: Parser14
!! wikitext
-== onmouseover= ==
+==onmouseover===
http://__TOC__
!! html/php
<h2><span class="mw-headline" id="onmouseover.3D">onmouseover=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: onmouseover=">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
-http://<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+http://<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="#onmouseover.3D"><span class="tocnumber">1</span> <span class="toctext">onmouseover=</span></a></li>
</ul>
!! html/php+tidy
<h2><span class="mw-headline" id="onmouseover.3D">onmouseover=</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: onmouseover=">edit</a><span class="mw-editsection-bracket">]</span></span></h2><p>
-http://</p><div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+http://</p><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="#onmouseover.3D"><span class="tocnumber">1</span> <span class="toctext">onmouseover=</span></a></li>
</ul>
</div>
!! html/parsoid
-<h2 id="onmouseover="><span id="onmouseover.3D" typeof="mw:FallbackId"></span> onmouseover= </h2>
+<h2 id="onmouseover="><span id="onmouseover.3D" typeof="mw:FallbackId"></span>onmouseover=</h2>
<p><a rel="mw:ExtLink" class="external free" href="http://__TOC__" data-parsoid='{"stx":"url"}'>http://__TOC__</a></p>
!! end
!! 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&action=edit&section=1" title="Edit section: a">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<table style="__TOC__">
<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&action=edit&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="__TOC__">
+<tbody><tr><td></td></tr>
+</tbody></table>
!! html/parsoid
<h2 id="a">a</h2>
<table style="__TOC__"></table>
Fuzz testing: Parser21
!! wikitext
{|
-! irc://{{ftp://a" onmouseover="alert('hello world');"
+!irc://{{ftp://a" onmouseover="alert('hello world');"
|
!! html
<table>
<tr>
-<th> <a rel="nofollow" class="external free" href="irc://{{ftp://a">irc://{{ftp://a</a>" onmouseover="alert('hello world');"
+<th><a rel="nofollow" class="external free" href="irc://{{ftp://a">irc://{{ftp://a</a>" onmouseover="alert('hello world');"
</th>
<td>
</td>
!! end
-# Known to produce bad XML for now
+## Remex doesn't account for fostered content.
+## Known to produce bad XML for now
!! test
Fuzz testing: Parser24
!! options
</tr>
</table>
-!! html/parsoid
-<p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'>{{{|
-<u class="|" data-parsoid='{"stx":"html","a":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":null},"sa":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":""},"autoInsertedEnd":true}'><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/>}}}} >
-<br style="onmouseover='alert(document.cookie);' " data-parsoid='{"stx":"html","selfClose":true}'/></u></p><p data-parsoid='{"fostered":true,"autoInsertedEnd":true}'><u class="|" data-parsoid='{"stx":"html","a":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":null},"sa":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":""},"autoInsertedEnd":true,"autoInsertedStart":true}'>MOVE YOUR MOUSE CURSOR OVER THIS TEXT</u></p><table data-parsoid='{"autoInsertedEnd":true}'>
+!! html/php+tidy
+{{{|
+<u class="|">}}}} >
+<br style="onmouseover='alert(document.cookie);'" />
+MOVE YOUR MOUSE CURSOR OVER THIS TEXT
+</u><table><tbody><tr>
+<td>
+</td>
+</tr>
+</tbody></table><p><u class="|">
+</u></p>
+!! html/parsoid
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>
+{{{|
+<u class="|" data-parsoid='{"stx":"html","a":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":null},"sa":{"{{{{SSSll!!!!!!!VVVV)]]][[Special:*xxxxxxx--":""},"autoInsertedEnd":true}'><meta typeof="mw:Includes/NoInclude" data-parsoid='{"src":"<noinclude>"}'/>}}}} >
+<br style="onmouseover='alert(document.cookie);' " data-parsoid='{"stx":"html","selfClose":true}'/>
-<tbody><tr data-parsoid='{"autoInsertedEnd":true,"autoInsertedStart":true}'><td data-parsoid='{"autoInsertedEnd":true}'></td></tr></tbody></table>
+MOVE YOUR MOUSE CURSOR OVER THIS TEXT</u></p>
+<table data-parsoid='{"autoInsertedEnd":true}'><tbody><tr data-parsoid='{"autoInsertedStart":true}'><td></td></tr></tbody></table>
!! end
# Note: the current result listed for this is not what the original one was,
<pre dir=" "></pre>
!! html/parsoid
-<pre typeof="mw:Extension/pre" about="#mwt2" dir="
-" data-mw='{"name":"pre","attrs":{"dir":"\n"},"body":{"extsrc":""}}'></pre>
+<pre dir="
+" typeof="mw:Extension/pre" about="#mwt2"data-mw='{"name":"pre","attrs":{"dir":"\n"},"body":{"extsrc":""}}'></pre>
!! end
!! test
<pre dir="{{echo|ltr}}"></pre>
!! html/parsoid
-<pre typeof="mw:Extension/pre" about="#mwt2" dir="{{echo|ltr}}" data-mw='{"name":"pre","attrs":{"dir":"{{echo|ltr}}"},"body":{"extsrc":""}}'></pre>
+<pre dir="{{echo|ltr}}" typeof="mw:Extension/pre" about="#mwt2" data-mw='{"name":"pre","attrs":{"dir":"{{echo|ltr}}"},"body":{"extsrc":""}}'></pre>
!! end
!! test
<p><b>Bold paragraph
</p><p>New wiki paragraph</b>
</p>
+!! html/php+tidy
+<p><b>Bold paragraph
+</b></p><p><b>New wiki paragraph
+</b></p>
!! html/parsoid
<p><b>Bold paragraph</b>
</p><p>New wiki paragraph
!! test
Handling of 
 in URLs
!! wikitext
-** irc://
a
+*irc://
a
!! html/php
-<ul><li><ul><li> <a rel="nofollow" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul></li></ul>
+<ul><li><a rel="nofollow" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul>
!! html/parsoid
-<ul><li><ul><li> <a rel="mw:ExtLink" class="external free" href="irc://%0Aa" data-parsoid='{"stx":"url","a":{"href":"irc://%0Aa"},"sa":{"href":"irc://&#x0A;a"}}'>irc://%0Aa</a></li></ul></li></ul>
+<ul><li><a rel="mw:ExtLink" class="external free" href="irc://%0Aa" data-parsoid='{"stx":"url","a":{"href":"irc://%0Aa"},"sa":{"href":"irc://&#x0A;a"}}'>irc://%0Aa</a></li></ul>
!! end
!! test
Handling of %0A in URLs
!! wikitext
-** irc://%0Aa
+*irc://%0Aa
!! html/php
-<ul><li><ul><li> <a rel="nofollow" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul></li></ul>
+<ul><li><a rel="nofollow" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul>
!! html/parsoid
-<ul><li><ul><li> <a rel="mw:ExtLink" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul></li></ul>
+<ul><li><a rel="mw:ExtLink" class="external free" href="irc://%0Aa">irc://%0Aa</a></li></ul>
!! end
# The PHP parser strips the empty tags out for giggles; parsoid doesn't.
'''''
!! html/php
!! html/parsoid
-<b><i></i></b>
+<p><b><i></i></b></p>
!! end
# same html as previous, but wikitext adjusted to match parsoid html2wt
!! options
title=[[Parser test]]
!! wikitext
-* {{PAGENAME}}
-* {{PAGENAMEE}}
-* {{FULLPAGENAME}}
-* {{FULLPAGENAMEE}}
-* {{BASEPAGENAME}}
-* {{BASEPAGENAMEE}}
-* {{SUBPAGENAME}}
-* {{SUBPAGENAMEE}}
-* {{ROOTPAGENAME}}
-* {{ROOTPAGENAMEE}}
-* {{TALKPAGENAME}}
-* {{TALKPAGENAMEE}}
-* {{SUBJECTPAGENAME}}
-* {{SUBJECTPAGENAMEE}}
-* {{NAMESPACEE}}
-* {{NAMESPACE}}
-* {{NAMESPACENUMBER}}
-* {{TALKSPACE}}
-* {{TALKSPACEE}}
-* {{SUBJECTSPACE}}
-* {{SUBJECTSPACEE}}
-* {{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}}
-!! html
-<ul><li> Parser test</li>
-<li> Parser_test</li>
-<li> Parser test</li>
-<li> Parser_test</li>
-<li> Parser test</li>
-<li> Parser_test</li>
-<li> Parser test</li>
-<li> Parser_test</li>
-<li> Parser test</li>
-<li> Parser_test</li>
-<li> Talk:Parser test</li>
-<li> Talk:Parser_test</li>
-<li> Parser test</li>
-<li> Parser_test</li>
-<li> </li>
-<li> </li>
-<li> 0</li>
-<li> Talk</li>
-<li> Talk</li>
-<li> </li>
-<li> </li>
-<li> <a href="/index.php?title=Template:Dynamic&action=edit&redlink=1" class="new" title="Template:Dynamic (page does not exist)">Template:Dynamic</a></li></ul>
+*{{PAGENAME}}
+*{{PAGENAMEE}}
+*{{FULLPAGENAME}}
+*{{FULLPAGENAMEE}}
+*{{BASEPAGENAME}}
+*{{BASEPAGENAMEE}}
+*{{SUBPAGENAME}}
+*{{SUBPAGENAMEE}}
+*{{ROOTPAGENAME}}
+*{{ROOTPAGENAMEE}}
+*{{TALKPAGENAME}}
+*{{TALKPAGENAMEE}}
+*{{SUBJECTPAGENAME}}
+*{{SUBJECTPAGENAMEE}}
+*{{NAMESPACEE}}
+*{{NAMESPACE}}
+*{{NAMESPACENUMBER}}
+*{{TALKSPACE}}
+*{{TALKSPACEE}}
+*{{SUBJECTSPACE}}
+*{{SUBJECTSPACEE}}
+*{{Dynamic|{{NUMBEROFUSERS}}|{{NUMBEROFPAGES}}|{{CURRENTVERSION}}|{{CONTENTLANGUAGE}}|{{DIRECTIONMARK}}|{{CURRENTTIMESTAMP}}|{{NUMBEROFARTICLES}}}}
+!! html
+<ul><li>Parser test</li>
+<li>Parser_test</li>
+<li>Parser test</li>
+<li>Parser_test</li>
+<li>Parser test</li>
+<li>Parser_test</li>
+<li>Parser test</li>
+<li>Parser_test</li>
+<li>Parser test</li>
+<li>Parser_test</li>
+<li>Talk:Parser test</li>
+<li>Talk:Parser_test</li>
+<li>Parser test</li>
+<li>Parser_test</li>
+<li></li>
+<li></li>
+<li>0</li>
+<li>Talk</li>
+<li>Talk</li>
+<li></li>
+<li></li>
+<li><a href="/index.php?title=Template:Dynamic&action=edit&redlink=1" class="new" title="Template:Dynamic (page does not exist)">Template:Dynamic</a></li></ul>
!! end
### Note: Above tests excludes the "{{NUMBEROFADMINS}}" magic word because it generates a MySQL error when included.
</ul>
!! end
- ## Whoops, Parsoid shouldn't be parsing templates in the attribute caption!
!! test
Gallery with template inside caption
!! options
</gallery>
!! html/php
<ul class="gallery mw-gallery-traditional">
- <li class='gallerycaption'>{{echo|hi}}</li>
+ <li class='gallerycaption'>hi</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/File:Foobar.jpg" class="image"><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">
</ul>
!! end
+ !! test
+ Gallery with wikitext inside gallery caption
+ !! wikitext
+ <gallery caption="# List item
+
+ Text '''bold''' [[link]] {{ns:-1}}
+
+ [[File:Foobar.jpg|thumb|File in gallery caption]]">
+ File:Foobar.jpg|Image caption
+ </gallery>
+ !! html/php
+ <ul class="gallery mw-gallery-traditional">
+ <li class='gallerycaption'># List item Text <b>bold</b> <a href="/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">link</a> Special <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>File in gallery caption</div></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/File:Foobar.jpg" class="image"><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>Image caption
+ </p>
+ </div>
+ </div></li>
+ </ul>
+
+ !! end
+
!! test
Gallery with wikitext inside caption
!! options
</ul>
!! end
+!! test
+Serialize gallery image captions on a line
+!! options
+parsoid={
+ "modes": ["html2wt"],
+ "nativeGallery": true
+}
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px;"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><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"><p>hi</p><p>ho</p></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px;"><figure-inline typeof="mw:Image"><a href="./File:Foobar.jpg"><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">hi<br />ho</div></li>
+</ul>
+!! wikitext
+<gallery>
+File:Foobar.jpg| hi ho
+File:Foobar.jpg|hi<br />ho
+</gallery>
+!! end
+
!! test
HTML Hex character encoding (spells the word "JavaScript")
!! options
; Surrogate: ��
; This is an okay astral character: 💩
!! html+tidy
-<dl><dt> Null</dt>
-<dd> &#00;</dd>
-<dt> FF</dt>
-<dd> &#xC;</dd>
-<dt> CR</dt>
-<dd> &#xD;</dd>
-<dt> Control (low)</dt>
-<dd> &#8;</dd>
-<dt> Control (high)</dt>
-<dd> &#x7F; &#x9F;</dd>
-<dt> Surrogate</dt>
-<dd> &#xD83D;&#xDCA9;</dd>
-<dt> This is an okay astral character</dt>
-<dd> 💩</dd></dl>
+<dl><dt>Null</dt>
+<dd>&#00;</dd>
+<dt>FF</dt>
+<dd>&#xC;</dd>
+<dt>CR</dt>
+<dd>&#xD;</dd>
+<dt>Control (low)</dt>
+<dd>&#8;</dd>
+<dt>Control (high)</dt>
+<dd>&#x7F; &#x9F;</dd>
+<dt>Surrogate</dt>
+<dd>&#xD83D;&#xDCA9;</dd>
+<dt>This is an okay astral character</dt>
+<dd>💩</dd></dl>
!! end
!! test
Double RFC
!! wikitext
RFC RFC 1234
-!! html
+!! html/php
<p>RFC <a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc1234">RFC 1234</a>
</p>
+!! html/parsoid
+<p>RFC <a href="https://tools.ietf.org/html/rfc1234" rel="mw:ExtLink" class="external mw-magiclink">RFC 1234</a></p>
!! end
!! test
Double RFC with a wiki link
!! wikitext
RFC [[RFC 1234]]
-!! html
+!! html/php
<p>RFC <a href="/index.php?title=RFC_1234&action=edit&redlink=1" class="new" title="RFC 1234 (page does not exist)">RFC 1234</a>
</p>
+!! html/parsoid
+<p>RFC <a rel="mw:WikiLink" href="./RFC_1234" title="RFC 1234">RFC 1234</a></p>
!! end
!! test
<p><a class="external mw-magiclink-rfc" rel="nofollow" href="https://tools.ietf.org/html/rfc983">RFC 983</a> 987
</p>
!! html/parsoid
-<p><a href="https://tools.ietf.org/html/rfc983" rel="mw:ExtLink" class="external text" data-parsoid='{"stx":"magiclink"}'>RFC 983</a><span typeof="mw:Entity" data-parsoid='{"src":"&#x20;","srcContent":" "}'> </span>987</p>
+<p><a href="https://tools.ietf.org/html/rfc983" rel="mw:ExtLink" class="external mw-magiclink" data-parsoid='{"stx":"magiclink"}'>RFC 983</a><span typeof="mw:Entity" data-parsoid='{"src":"&#x20;","srcContent":" "}'> </span>987</p>
!! end
!! test
!! 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":"<script>alert(1);</script>"}}'>alert(1);</script></p>
!! end
!! test
!! test
Definition list code coverage
!! wikitext
-; title : def
-; title : def
-;title: def
+;title :def
+;title :def
+;title:def
!! html/php
-<dl><dt> title  </dt>
-<dd> def</dd>
-<dt> title </dt>
-<dd> def</dd>
+<dl><dt>title</dt>
+<dd>def</dd>
+<dt>title</dt>
+<dd>def</dd>
<dt>title</dt>
-<dd> def</dd></dl>
+<dd>def</dd></dl>
!! html/parsoid
-<dl><dt> title <span typeof="mw:Placeholder"> </span></dt><dd> def</dd>
-<dt> title<span typeof="mw:Placeholder"> </span></dt><dd> def</dd>
-<dt>title</dt><dd> def</dd></dl>
+<dl><dt>title </dt><dd>def</dd>
+<dt>title </dt><dd>def</dd>
+<dt>title</dt><dd>def</dd></dl>
!! end
!! test
=====5=====
==2==
!! html
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#2"><span class="tocnumber">1</span> <span class="toctext">2</span></a>
<ul>
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
-=== _ +:.3A%3A _ &&]] x ===
+===_ +:.3A%3A _ &&]] x===
{{anchorencode: _ +:.3A%3A _ &&]] x}}
__NOEDITSECTION__
!! html/php
<p>+:.3A%3A_&&]]_x
</p>
!! html/parsoid
-<h3 id="+:.3A%3A_&&]]_x"><span id=".2B:.3A.253A_.26.26.5D.5D_x" typeof="mw:FallbackId"></span> _ +:.3A%3A _ &<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&","dsr":[18,23,null,null]}'>&</span>]] x </h3>
+<h3 id="+:.3A%3A_&&]]_x"><span id=".2B:.3A.253A_.26.26.5D.5D_x" typeof="mw:FallbackId"></span>_ +:.3A%3A _ &<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&","dsr":[18,23,null,null]}'>&</span>]] x</h3>
<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"anchorencode: _ +:.3A%3A _ &&amp;]] x","function":"anchorencode"},"params":{},"i":0}}]}'>+:.3A%3A_&&<span typeof="mw:Entity">]</span><span typeof="mw:Entity">]</span>_x</p>
<meta property="mw:PageProp/noeditsection"/>
!! end
!! config
wgFragmentMode=[ 'legacy' ]
!! wikitext
-=== _ +:.3A%3A&&]] ===
+===_ +:.3A%3A&&]]===
{{anchorencode: _ +:.3A%3A&&]] }}
__NOEDITSECTION__
!! html/php
!! options
language=sr variant=sr-ec
!! wikitext
-== -{Naslov}- ==
+==-{Naslov}-==
Note that even an unprotected headline ID is not affected by language
conversion:
-== Latinski ==
+==Latinski==
!! html/php
-<h2><span id="-.7BNaslov.7D-"></span><span class="mw-headline" id="-{Naslov}-">Naslov</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Уреди одељак „Naslov“">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span id="-.7BNaslov.7D-"></span><span class="mw-headline" id="-{Naslov}-">Naslov</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Уредите одељак „Naslov”">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
<p>Ноте тхат евен ан унпротецтед хеадлине ИД ис нот аффецтед бy лангуаге
цонверсион:
</p>
-<h2><span class="mw-headline" id="Latinski">Латински</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Уреди одељак „Латински“">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Latinski">Латински</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Уредите одељак „Латински”">уреди</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html/parsoid
-<h2 id="-{Naslov}-"><span id="-.7BNaslov.7D-" typeof="mw:FallbackId"></span> <span typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"Naslov"}}'></span> </h2>
+<h2 id="-{Naslov}-"><span id="-.7BNaslov.7D-" typeof="mw:FallbackId"></span><span typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"Naslov"}}'></span></h2>
<p>Note that even an unprotected headline ID is not affected by language
conversion:</p>
<span>ad
</span></div></span></div></span>
!! html/parsoid
-<p><span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a</span></p><div typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[10,16,5,0]}'>c</div>"}}'></div><p>d</p>
+<span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a<div typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[10,16,5,0]}'>c</div>"}}'></div>d
-<p><span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a</span></p><div typeof="mw:LanguageVariant" data-mw-variant='{"filter":{"l":["zh","zh-hans","zh-hant"],"t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[50,56,5,0]}'>c</div>"}}'></div><p>d</p>
+<span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a<div typeof="mw:LanguageVariant" data-mw-variant='{"filter":{"l":["zh","zh-hans","zh-hant"],"t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[50,56,5,0]}'>c</div>"}}'></div>d
-<p><span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a<meta typeof="mw:LanguageVariant" data-mw-variant='{"add":true,"oneway":[{"f":"0","l":"zh-cn","t":"x<span data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[82,89,6,0]}'>y</span>"},{"f":"0","l":"zh-tw","t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[100,106,5,0]}'>c</div>"}]}'/>d</span></p>
+<p><span data-parsoid='{"stx":"html","autoInsertedEnd":true}'>a<meta typeof="mw:LanguageVariant" data-mw-variant='{"add":true,"oneway":[{"f":"0","l":"zh-cn","t":"x<span data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[82,89,6,0]}'>y</span>"},{"f":"0","l":"zh-tw","t":"b<div data-parsoid='{\"stx\":\"html\",\"autoInsertedEnd\":true,\"dsr\":[100,106,5,0]}'>c</div>"}]}'/>d</span></p></span></span>
!! end
!! test
!! html/php
<p><a rel="nofollow" class="external free" href="http://www.google.com">http://www.google.com</a>
<a rel="nofollow" class="external free" href="gopher://www.google.com">gopher://www.google.com</a>
-<a rel="nofollow" class="external free" href="http://www.google.com">http://www.google.com</a>
-<a rel="nofollow" class="external free" href="gopher://www.google.com">gopher://www.google.com</a>
+<a rel="nofollow" class="external text" href="http://www.google.com">http://www.google.com</a>
+<a rel="nofollow" class="external text" href="gopher://www.google.com">gopher://www.google.com</a>
<a rel="nofollow" class="external text" href="https://www.google.com">irc://www.google.com</a>
<a rel="nofollow" class="external text" href="ftp://www.google.com">www.гоогле.цом/фтп://дир</a>
<a rel="nofollow" class="external text" href="//www.google.com">www.гоогле.цом</a>
!! html/parsoid
<p><a rel="mw:ExtLink" class="external free" href="http://www.google.com">http://www.google.com</a>
<a rel="mw:ExtLink" class="external free" href="gopher://www.google.com">gopher://www.google.com</a>
-<a rel="mw:ExtLink" class="external free" href="http://www.google.com">http://www.google.com</a>
-<a rel="mw:ExtLink" class="external free" href="gopher://www.google.com">gopher://www.google.com</a>
+<a rel="mw:ExtLink" class="external text" href="http://www.google.com">http://www.google.com</a>
+<a rel="mw:ExtLink" class="external text" href="gopher://www.google.com">gopher://www.google.com</a>
<a rel="mw:ExtLink" class="external text" href="https://www.google.com">irc://www.google.com</a>
<a rel="mw:ExtLink" class="external text" href="ftp://www.google.com">www.google.com/ftp://dir</a>
<a rel="mw:ExtLink" class="external text" href="//www.google.com">www.google.com</a></p>
!! wikitext
[[Датотека:Foobar.jpg|thumb|-{R|caption:}-]]
!! html/php
-<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0: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/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0:Foobar.jpg" class="internal" title="Повећај"></a></div>caption:</div></div></div>
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0: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/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0:Foobar.jpg" class="internal" title="Повећајте"></a></div>caption:</div></div></div>
!! html/parsoid
<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"}]}'><a href="./Датотека:Foobar.jpg"><img resource="./Датотека: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"/></a><figcaption><span typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"caption:"}}' data-parsoid='{"fl":["R"]}'></span></figcaption></figure>
<dt>-{zh-cn:AAA</dt></b></dl><p><b>
</b></p>
!! html/parsoid
-<dl><dt data-parsoid='{"dsr":[0,11,1,0]}'><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'>foo:bar</b></dt><b data-parsoid='{"stx":"html","autoInsertedEnd":true,"autoInsertedStart":true}'>
-<dt data-parsoid='{"dsr":[12,20,1,0]}'>-{zh-cn</dt>
-<dd data-parsoid='{"stx":"row","dsr":[20,24,1,0]}'>AAA</dd>
-</b></dl>
+<dl><dt data-parsoid='{}'><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'>foo:bar</b></dt><b data-parsoid='{"stx":"html","autoInsertedEnd":true,"autoInsertedStart":true}'>
+<dt data-parsoid='{}'>-{zh-cn</dt><dd data-parsoid='{"stx":"row"}'>AAA</dd></b></dl>
!! end
!! test
<table>
<tr>
-<td> B
+<td>B
</td></tr></table>
!! html/parsoid
!! test
T2529: Uncovered bullet
!! wikitext
-* Foo {{bullet}}
+*Foo {{bullet}}
!! html
-<ul><li> Foo </li>
-<li> Bar</li></ul>
+<ul><li>Foo</li>
+<li>Bar</li></ul>
!! end
!! test
T2529: Uncovered bullet in a deeply nested list
!! wikitext
-******* Foo {{bullet}}
+*******Foo {{bullet}}
!! html
-<ul><li><ul><li><ul><li><ul><li><ul><li><ul><li><ul><li> Foo </li></ul></li></ul></li></ul></li></ul></li></ul></li></ul></li>
-<li> Bar</li></ul>
+<ul><li><ul><li><ul><li><ul><li><ul><li><ul><li><ul><li>Foo</li></ul></li></ul></li></ul></li></ul></li></ul></li></ul></li>
+<li>Bar</li></ul>
!! end
</p>
<table>
<tr>
-<td> 1 </td>
-<td> 2
+<td>1</td>
+<td>2
</td></tr>
<tr>
-<td> 3 </td>
-<td> 4
+<td>3</td>
+<td>4
</td></tr></table>
<p>y
</p>
!! test
T2529: Uncovered bullet in parser function result
!! wikitext
-* Foo {{lc:{{bullet}} }}
+*Foo {{lc:{{bullet}} }}
!! html
-<ul><li> Foo </li>
-<li> bar</li></ul>
+<ul><li>Foo</li>
+<li>bar</li></ul>
!! end
!! end
# doBlockLevels screws up this output and Remex cleans up as much as it can.
-# Parsoid seems to do a better job here since its p-wrapper is probably smarter.
!! test
Nesting tags, paragraphs on lines which begin with <div>
!! wikitext
</strong></p><strong></strong><p><strong>B</strong>
</p>
!! html/parsoid
-<div></div>
-<p><strong>A
-B</strong>
-</p>
+<div data-parsoid='{"stx":"html"}'></div><p><strong data-parsoid='{"stx":"html","autoInsertedEnd":true}'>A</strong></p>
+<p><strong data-parsoid='{"stx":"html","autoInsertedStart":true}'>B</strong></p>
!! end
# T8200: <blockquote> should behave like <div> with respect to line breaks
!! end
-# FIXME: Why does/should the blockquote+div combo suppress p-wrapping here?
+## This is a corner case interaction between the paragraph wrapping in the
+## php parser's BlockLevelPass and Remex. `doBlockLevels` has a notion of
+## some tags which close paragraphs (and thus prevent wrapping on their line),
+## of which "div" is one, but do p-wrapping inside them. These are referred
+## to as "never suppressing". Remex, for its part, doesn't traverse into
+## "div"s to p-wrap. Hence, we only get this partial wrapping.
!! test
Paragraphs inside blockquotes/divs (no extra line breaks)
!! wikitext
!! wikitext
/* External links */ removed bogus entries
!! html/php
-<a href="/wiki/Main_Page#External_links" title="Main Page">→</a><span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
+<a href="/wiki/Main_Page#External_links" title="Main Page">→External links</a><span dir="auto"><span class="autocomment">: </span> removed bogus entries</span>
!!end
!! test
!! wikitext
pre-comment text /* External links */ removed bogus entries
!! html/php
-pre-comment text <a href="/wiki/Main_Page#External_links" title="Main Page">→</a><span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
+pre-comment text <a href="/wiki/Main_Page#External_links" title="Main Page">→External links</a><span dir="auto"><span class="autocomment">: </span> removed bogus entries</span>
!!end
!! test
!! wikitext
/* External links */ removed bogus entries
!! html/php
-<a href="#External_links">→</a><span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span>
+<a href="#External_links">→External links</a><span dir="auto"><span class="autocomment">: </span> removed bogus entries</span>
!!end
!! test
!! wikitext
/* __hello__world__ */
!! html/php
-<a href="/wiki/Main_Page#hello_world" title="Main Page">→</a><span dir="auto"><span class="autocomment">__hello__world__</span></span>
+<a href="/wiki/Main_Page#hello_world" title="Main Page">→__hello__world__</a>
!! end
!! test
Bad images - basic functionality
!! wikitext
[[File:Bad.jpg]]
-!! DISABLED/html/php
+!! html/php+disabled
!! html/parsoid
<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"bad-image","message":"This image is blacklisted in this context."}]}'><a href="./File:Bad.jpg"><img resource="./File:Bad.jpg" height="220" width="220"/></a></span></p>
!! end
Foo bar
[[File:Bad.jpg]]
Bar foo
-!! DISABLED/html/php
+!! html/php+disabled
<p>Foo bar
</p><p>Bar foo
</p>
<indicator name="02">[[Main Page]]</indicator>
<indicator name="03">[[File:Foobar.jpg|25px|link=]]</indicator>
<indicator name="04">[[File:Foobar.jpg|25px]]</indicator>
-<indicator name="05">* foo
-* bar</indicator>
+<indicator name="05">*foo
+*bar</indicator>
<indicator name="06"><nowiki>foo</nowiki></indicator>
<indicator name="07"> Preformatted</indicator>
<indicator name="08"><div>Broken tag</indicator>
<indicator name="09">{| class=wikitable
-| cell
+|cell
|}</indicator>
<indicator name="10">Two
02=<a href="/wiki/Main_Page" title="Main Page">Main Page</a>
03=<img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/25px-Foobar.jpg" width="25" height="3" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/38px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg 2x" />
04=<a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/25px-Foobar.jpg" width="25" height="3" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/38px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/50px-Foobar.jpg 2x" /></a>
-05=<ul><li> foo</li>
-<li> bar</li></ul>
+05=<ul><li>foo</li>
+<li>bar</li></ul>
06=foo
07=<pre>Preformatted
09=<table class="wikitable">
<tr>
-<td> cell
+<td>cell
</td></tr></table>
10=<p>Two
<div style="width:50% !important"> </div>
<div style="width:50% !important"> </div>
<div style="width:50% !important"> </div>
-<div style="border : solid;"> </div>
+<div style="border : solid;"> </div>
!! html/parsoid
<div style="width:50% !important" data-parsoid='{"stx":"html"}'><span typeof="mw:Entity" data-parsoid='{"srcContent":" "}'> </span></div>
!! end
+!! test
+French spaces in wikitext
+!! wikitext
+foo ! bar ? bat 50 % is less than 75 %.
+
+Hello : this ; is « something ‹ else › again »
+!! html
+<p>foo ! bar ? bat 50 % is less than 75 %.
+</p><p>Hello : this ; is « something ‹ else › again »
+</p>
+!! end
+
+# It would be reasonable for Parsoid and PHP to differ here.
+# The PHP behavior is arguably a bug.
+!! test
+Corner case: french spaces in definition list
+!! wikitext
+;foo : bar
+!! html+tidy
+<dl><dt>foo </dt>
+<dd>bar</dd></dl>
+!! end
+
+!! test
+T5158: Test for French spaces in attributes
+!! wikitext
+<br style=" clear : both ; " />
+!! html/php
+<p><br style="clear : both ;" />
+</p>
+!! end
+
!! test
HTML5 data attributes
!! wikitext
title=[[Main Page]]
!! wikitext
__TOC__
-== ''Lost'' episodes ==
+==''Lost'' episodes==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Lost_episodes"><span class="tocnumber">1</span> <span class="toctext"><i>Lost</i> episodes</span></a></li>
</ul>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Lost_episodes" data-parsoid='{}'> <i>Lost</i> episodes </h2>
+<h2 id="Lost_episodes" data-parsoid='{}'><i>Lost</i> episodes</h2>
!! end
!! test
title=[[Main Page]]
!! wikitext
__TOC__
-== '''should be bold''' then normal text ==
+=='''should be bold''' then normal text==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#should_be_bold_then_normal_text"><span class="tocnumber">1</span> <span class="toctext"><b>should be bold</b> then normal text</span></a></li>
</ul>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="should_be_bold_then_normal_text" data-parsoid='{}'> <b>should be bold</b> then normal text </h2>
+<h2 id="should_be_bold_then_normal_text" data-parsoid='{}'><b>should be bold</b> then normal text</h2>
!! end
!! test
title=[[Main Page]]
!! wikitext
__TOC__
-== Image [[Image:foobar.jpg]] ==
+==Image [[Image:foobar.jpg]]==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Image"><span class="tocnumber">1</span> <span class="toctext">Image</span></a></li>
</ul>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Image" data-parsoid='{}'> Image <figure-inline class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><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":"Image:foobar.jpg"}}'/></a></figure-inline> </h2>
+<h2 id="Image" data-parsoid='{}'>Image <figure-inline class="mw-default-size" typeof="mw:Image"><a href="./File:Foobar.jpg"><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":"Image:foobar.jpg"}}'/></a></figure-inline></h2>
!! end
!! test
title=[[Main Page]]
!! wikitext
__TOC__
-== <blockquote>Quote</blockquote> ==
+==<blockquote>Quote</blockquote>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
</ul>
<h2><span class="mw-headline" id="Quote"><blockquote>Quote</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&action=edit&section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html/php+tidy
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Quote"><span class="tocnumber">1</span> <span class="toctext">Quote</span></a></li>
</ul>
<h2><span class="mw-headline" id="Quote"><blockquote><p>Quote</p></blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Main_Page&action=edit&section=1" title="Edit section: Quote">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Quote" data-parsoid='{}'> <blockquote>Quote</blockquote> </h2>
+<h2 id="Quote" data-parsoid='{}'><blockquote><p>Quote</p></blockquote></h2>
!! end
!! test
title=[[Main Page]]
!! wikitext
__TOC__
-== Proof: 2 < 3 ==
+==Proof: 2 < 3==
<small>Hanc marginis exiguitas non caperet.</small>
QED
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Proof:_2_<_3"><span class="tocnumber">1</span> <span class="toctext">Proof: 2 < 3</span></a></li>
</ul>
</p>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Proof:_2_<_3" data-parsoid='{}'><span id="Proof:_2_.3C_3" typeof="mw:FallbackId"></span> Proof: 2 < 3 </h2>
+<h2 id="Proof:_2_<_3" data-parsoid='{}'><span id="Proof:_2_.3C_3" typeof="mw:FallbackId"></span>Proof: 2 < 3</h2>
<p><small>Hanc marginis exiguitas non caperet.</small>
QED</p>
!! end
Multiple tags in TOC
!! wikitext
__TOC__
-== <i>Foo</i> <b>Bar</b> ==
+==<i>Foo</i> <b>Bar</b>==
-== <i>Foo</i> <blockquote>Bar</blockquote> ==
+==<i>Foo</i> <blockquote>Bar</blockquote>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Foo_Bar"><span class="tocnumber">1</span> <span class="toctext"><i>Foo</i> <b>Bar</b></span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#Foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext"><i>Foo</i> Bar</span></a></li>
<h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i> <blockquote>Bar</blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html/php+tidy
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Foo_Bar"><span class="tocnumber">1</span> <span class="toctext"><i>Foo</i> <b>Bar</b></span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#Foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext"><i>Foo</i> Bar</span></a></li>
<h2><span class="mw-headline" id="Foo_Bar_2"><i>Foo</i> <blockquote><p>Bar</p></blockquote></span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: Foo Bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="Foo_Bar" data-parsoid='{}'> <i data-parsoid='{"stx":"html"}'>Foo</i> <b data-parsoid='{"stx":"html"}'>Bar</b> </h2>
+<h2 id="Foo_Bar" data-parsoid='{}'><i data-parsoid='{"stx":"html"}'>Foo</i> <b data-parsoid='{"stx":"html"}'>Bar</b></h2>
-<h2 id="Foo_Bar_2" data-parsoid='{}'> <i data-parsoid='{"stx":"html"}'>Foo</i> <blockquote>Bar</blockquote> </h2>
+<h2 id="Foo_Bar_2" data-parsoid='{}'><i data-parsoid='{"stx":"html"}'>Foo</i> <blockquote><p>Bar</p></blockquote></h2>
!! end
# Don't expect Parsoid to roundtrip this until the php parser comes closer to
parsoid=wt2html
!! wikitext
__TOC__
-== <sup class="in-h2">Hello</sup> ==
+==<sup class="in-h2">Hello</sup>==
-== <sup class="a > b">Evilbye</sup> ==
+==<sup class="a > b">Evilbye</sup>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Hello"><span class="tocnumber">1</span> <span class="toctext"><sup>Hello</sup></span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#b.22.3EEvilbye"><span class="tocnumber">2</span> <span class="toctext"><sup> b">Evilbye</sup></span></a></li>
!! html/parsoid
<meta property="mw:PageProp/toc" />
-<h2 id="Hello"> <sup class="in-h2" data-parsoid='{"stx":"html"}'>Hello</sup> </h2>
+<h2 id="Hello"><sup class="in-h2" data-parsoid='{"stx":"html"}'>Hello</sup></h2>
-<h2 id='b">Evilbye'><span id="b.22.3EEvilbye" typeof="mw:FallbackId"></span> <sup class="a " data-parsoid='{"stx":"html"}'> b">Evilbye</sup> </h2>
+<h2 id='b">Evilbye'><span id="b.22.3EEvilbye" typeof="mw:FallbackId"></span><sup class="a " data-parsoid='{"stx":"html"}'> b">Evilbye</sup></h2>
!! end
!! test
span tags with directionality in TOC
!! wikitext
__TOC__
-== <span dir="ltr">C++</span> ==
+==<span dir="ltr">C++</span>==
-== <span dir="rtl">זבנג!</span> ==
+==<span dir="rtl">זבנג!</span>==
-== <span style="font-style: italic">The attributes on these span tags must be deleted from the TOC</span> ==
+==<span style="font-style: italic">The attributes on these span tags must be deleted from the TOC</span>==
-== <span style="font-style: italic" dir="ltr">All attributes on these span tags must be deleted from the TOC</span> ==
+==<span style="font-style: italic" dir="ltr">All attributes on these span tags must be deleted from the TOC</span>==
-== <span dir="ltr" style="font-style: italic">Attributes after dir on these span tags must be deleted from the TOC</span> ==
+==<span dir="ltr" style="font-style: italic">Attributes after dir on these span tags must be deleted from the TOC</span>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#C.2B.2B"><span class="tocnumber">1</span> <span class="toctext"><span dir="ltr">C++</span></span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#.D7.96.D7.91.D7.A0.D7.92.21"><span class="tocnumber">2</span> <span class="toctext"><span dir="rtl">זבנג!</span></span></a></li>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="C++" data-parsoid='{}'><span id="C.2B.2B" typeof="mw:FallbackId"></span> <span dir="ltr">C++</span> </h2>
-<h2 id="זבנג!"><span id=".D7.96.D7.91.D7.A0.D7.92.21" typeof="mw:FallbackId"></span> <span dir="rtl">זבנג!</span> </h2>
-<h2 id="The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC"> <span style="font-style: italic">The attributes on these span tags must be deleted from the TOC</span> </h2>
-<h2 id="All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC"> <span style="font-style: italic" dir="ltr">All attributes on these span tags must be deleted from the TOC</span> </h2>
-<h2 id="Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC"> <span dir="ltr" style="font-style: italic">Attributes after dir on these span tags must be deleted from the TOC</span> </h2>
+<h2 id="C++" data-parsoid='{}'><span id="C.2B.2B" typeof="mw:FallbackId"></span><span dir="ltr">C++</span></h2>
+<h2 id="זבנג!"><span id=".D7.96.D7.91.D7.A0.D7.92.21" typeof="mw:FallbackId"></span><span dir="rtl">זבנג!</span></h2>
+<h2 id="The_attributes_on_these_span_tags_must_be_deleted_from_the_TOC"><span style="font-style: italic">The attributes on these span tags must be deleted from the TOC</span></h2>
+<h2 id="All_attributes_on_these_span_tags_must_be_deleted_from_the_TOC"><span style="font-style: italic" dir="ltr">All attributes on these span tags must be deleted from the TOC</span></h2>
+<h2 id="Attributes_after_dir_on_these_span_tags_must_be_deleted_from_the_TOC"><span dir="ltr" style="font-style: italic">Attributes after dir on these span tags must be deleted from the TOC</span></h2>
!! end
!! test
T74884: bdi element in ToC
!! wikitext
__TOC__
-== <bdi>test</bdi> ==
+==<bdi>test</bdi>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#test"><span class="tocnumber">1</span> <span class="toctext"><bdi>test</bdi></span></a></li>
</ul>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="test" data-parsoid='{}'> <bdi>test</bdi> </h2>
+<h2 id="test" data-parsoid='{}'><bdi>test</bdi></h2>
!! end
!! test
T35715: s/strike element in ToC
!! wikitext
__TOC__
-== <s>test</s> test <strike>test</strike> ==
+==<s>test</s> test <strike>test</strike>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#test_test_test"><span class="tocnumber">1</span> <span class="toctext"><s>test</s> test <strike>test</strike></span></a></li>
</ul>
!! html/parsoid
<meta property="mw:PageProp/toc" data-parsoid='{}'/>
-<h2 id="test_test_test" data-parsoid='{}'> <s>test</s> test <strike>test</strike> </h2>
+<h2 id="test_test_test" data-parsoid='{}'><s>test</s> test <strike>test</strike></h2>
!! end
!! test
-Empty <p> tag in TOC, removed by Sanitizer (T92892)
+T198618: style element in ToC
+!! options
+styletag=1
!! wikitext
__TOC__
-== x ==
+==<style>.foo {}</style>Style<style>.bar {}</style>==
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#x"><span class="tocnumber">1</span> <span class="toctext">x</span></a></li>
+<li class="toclevel-1 tocsection-1"><a href="#Style"><span class="tocnumber">1</span> <span class="toctext">Style</span></a></li>
</ul>
</div>
-<h2><span class="mw-headline" id="x">x</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: x">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<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&action=edit&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="x" data-parsoid='{}'> x </h2>
+<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
-!! article
+!! 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&action=edit&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="Script" data-parsoid='{}'><script typeof="mw:Extension/html" about="#mwt4" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"<script>alert(1);</script>"}}'>alert(1);</script>Script<script typeof="mw:Extension/html" about="#mwt6" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"<script>alert(1);</script>"}}'>alert(1);</script></h2>
+!! end
+
+!! test
+Empty <p> tag in TOC, removed by Sanitizer (T92892)
+!! wikitext
+__TOC__
+==x==
+!! 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="#x"><span class="tocnumber">1</span> <span class="toctext">x</span></a></li>
+</ul>
+</div>
+
+<h2><span class="mw-headline" id="x">x</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: x">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! html/parsoid
+<meta property="mw:PageProp/toc" data-parsoid='{}'/>
+<h2 id="x" data-parsoid='{}'>x</h2>
+!! end
+
+!! article
MediaWiki:T34057
!! text
== {{int:headline_sample}} ==
Ignore pipe between table row attributes
!! wikitext
{|
-| quux
+|quux
|- id=foo | style='color: red'
-| bar
+|bar
|}
!! html
<table>
<tr>
-<td> quux
+<td>quux
</td></tr>
<tr id="foo" style="color: red">
-<td> bar
+<td>bar
</td></tr></table>
!! end
<span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"padright:","function":"padright"},"params":{"1":{"wt":"3"},"2":{"wt":"abcde"}},"i":0}}]}'>abc</span></p>
!! end
+!! test
+Padleft and padright with non-numerical length (T180403)
+!! wikitext
+{{padleft:abcdef|junk}}
+{{padright:abcdef|junk}}
+!! html/php
+<p>abcdef
+abcdef
+</p>
+!! end
+
!!test
Special parser function
!! wikitext
notoc
!! wikitext
Lead
-== Section 1 ==
-== Section 2 ==
-== Section 3 ==
-== Section 4 ==
-== Section 5 ==
+==Section 1==
+==Section 2==
+==Section 3==
+==Section 4==
+==Section 5==
!! html
<p>Lead
</p>
###
!!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>
#### Parsoid-specific functionality tests
#### -----------------------------------------------------------------
-# T65642/T68749: Formatting elt fixup around images is cleaned up.
+# T65642/T68749: Formatting elt fixup around images.
# We know wt2wt will fail, but we expect selser to pass.
# Due to the nature of our testing, wt2wt and selser tests will enter the
# blacklist and we'll catch selser regressions based on changes to the
# blacklist entries for selser tests.
!! test
-1. Bad treebuilder fixup of formatting elt is cleaned up
+1. Treebuilder fixup of formatting elt
!! options
parsoid=wt2html,wt2wt
!! wikitext
[[Image:Foobar.jpg|right|Test]]
</small>
|}
+!! html/php+tidy
+<table>
+<tbody><tr>
+<td>
+<p><small>
+</small></p><small>
+<div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image" title="Test"><img alt="Test" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a></div>
+</small><p><small></small>
+</p>
+</td></tr></tbody></table>
!! html/parsoid
<table>
<tbody><tr><td>
-<small>
-<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><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><figcaption>Test</figcaption></figure>
-</small>
-</td></tr>
+<p><small data-parsoid='{"stx":"html","autoInsertedEnd":true}'></small></p><small data-parsoid='{"stx":"html","autoInsertedEnd":true,"autoInsertedStart":true}'>
+<figure class="mw-default-size mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><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><figcaption>Test</figcaption></figure></small>
+<p><small data-parsoid='{"stx":"html","autoInsertedStart":true}'></small></p></td></tr>
</tbody></table>
!! end
!! test
-2. Bad treebuilder fixup of formatting elt is cleaned up
+2. Treebuilder fixup of formatting elt
!! options
parsoid=wt2html,wt2wt
!! wikitext
'''foo[[File:Foobar.jpg|thumb|caption]]bar'''
<small>[[Image:Foobar.jpg|right|300px]]</small>
+!! html/php+tidy
+<p><b>foo</b></p><b><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>caption</div></div></div></b><p><b>bar</b>
+</p><small><div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a></div></small>
!! html/parsoid
+<p><b>foo</b></p><b><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>caption</figcaption></figure></b><p><b>bar</b></p>
-<p><b>foo</b></p>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><b>caption</b></figcaption></figure>
-<p><b>bar</b></p>
<small><figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></figure></small>
!! end
!! test
-3. Bad treebuilder fixup of formatting elt is cleaned up
+3. Treebuilder fixup of formatting elt
!! options
parsoid=wt2html,wt2wt
!! wikitext
<small>'''foo[[File:Foobar.jpg|thumb|caption]]bar'''</small>
+!! html/php+tidy
+<p><small><b>foo</b></small></p><small><b><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>caption</div></div></div></b></small><p><small><b>bar</b></small>
+</p>
!! html/parsoid
-<p><small><b>foo</b></small></p>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><small><b>caption</b></small></figcaption></figure>
-<p><small><b>bar</b></small></p>
+<p><small><b>foo</b></small></p><small><b><figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption>caption</figcaption></figure></b></small><p><small><b>bar</b></small></p>
!! end
!! test
-4. Bad treebuilder fixup of formatting elt is cleaned up: formatting tags around captionless images are ignored
+4. Treebuilder fixup of formatting elt: formatting tags around captionless images
!! options
parsoid=wt2html,wt2wt
!! wikitext
'''<small>[[Image:Foobar.jpg|right|300px]]</small>'''
+!! html/php+tidy
+<b><small><div class="floatright"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" width="300" height="34" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/450px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/600px-Foobar.jpg 2x" /></a></div></small></b>
!! html/parsoid
<b><small><figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/300px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="34" width="300"/></a></figure></small></b>
!! end
<section begin="2011-05-16" />
<section end="2014-04-10 (MW 1.23wmf22)" />
!! html/parsoid
-<p><span typeof="mw:Extension/section" about="#mwt4" data-mw='{"name":"section","attrs":{"begin":"2011-05-16"},"body":null}'>
+<p><span typeof="mw:Extension/section" about="#mwt4" data-mw='{"name":"section","attrs":{"begin":"2011-05-16"}}'>
</span>
-<span typeof="mw:Extension/section" about="#mwt6" data-mw='{"name":"section","attrs":{"end":"2014-04-10 (MW 1.23wmf22)"},"body":null}'>
+<span typeof="mw:Extension/section" about="#mwt6" data-mw='{"name":"section","attrs":{"end":"2014-04-10 (MW 1.23wmf22)"}}'>
</span></p>
!! end
!! test
Empty LI and TR nodes should not be stripped from top-level content
!! wikitext
-* a
+*a
*
-* b
+*b
+
{|
|-
|-
|}
!! html/parsoid
<ul>
-<li> a</li>
+<li>a</li>
<li class='mw-empty-elt'></li>
-<li> b</li>
+<li>b</li>
</ul>
<table>
<tbody>
!! end
+!! test
+Tables: 4e. Escape }
+!! options
+parsoid=html2wt
+!! html/parsoid
+<table>
+<tr><td>}</td></tr>
+<tr><td>x</td><td data-parsoid='{"stx":"row"}'>}</td></tr></table>
+</table>
+!! wikitext
+{|
+|<nowiki>}</nowiki>
+|-
+|x||}
+|}
+!! html/php
+<table>
+<tr>
+<td>}
+</td></tr>
+<tr>
+<td>x</td>
+<td>}
+</td></tr></table>
+
+!! end
+
+!! test
+Tables: 5. Empty table cells should get whitespace to avoid need for nowikis
+!! options
+parsoid=html2wt
+!! html/parsoid
+<table><tr><td></td><td align="center" data-parsoid='{"stx":"row"}'></td><td data-parsoid='{"stx":"row"}'></td></tr></table>
+
+<table><tr><td></td><td align="center"></td><td></td></tr></table>
+
+<table><tr><td></td><td align="center" data-parsoid='{"stx":"row", "startTagSrc":"{{!}}{{!}}"}'></td><td data-parsoid='{"stx":"row"}'></td></tr></table>
+
+<table><tr><th></th><th align="center" data-parsoid='{"stx":"row"}'></th><th data-parsoid='{"stx":"row"}'></th></tr></table>
+!! wikitext
+{|
+| || align="center" | ||
+|}
+
+{|
+|
+| align="center" |
+|
+|}
+
+{|
+| {{!}}{{!}} align="center" | ||
+|}
+
+{|
+! !! align="center" | !!
+|}
+!! html/php+tidy
+<table>
+<tbody><tr>
+<td></td>
+<td align="center"></td>
+<td>
+</td></tr></tbody></table>
+<table>
+<tbody><tr>
+<td>
+</td>
+<td align="center">
+</td>
+<td>
+</td></tr></tbody></table>
+<table>
+<tbody><tr>
+<td></td>
+<td align="center"></td>
+<td>
+</td></tr></tbody></table>
+<table>
+<tbody><tr>
+<th></th>
+<th align="center"></th>
+<th>
+</th></tr></tbody></table>
+!! end
+
!! test
T97430: Don't emit empty nowiki pairs around marker meta tags
!! options
!! html/php
<table>
<tr>
-<td> <foo
+<td><foo
</td>
-<td> bar>
+<td>bar>
</td></tr></table>
!! end
!!end
#### ----------------------- PRE --------------------------
-#### 1. Leading whitespace in SOL context should be escaped
-#### ------------------------------------------------------
!! test
1. Leading whitespace in SOL context should be escaped
!! options
==foo==
!! end
-!!test
+!! test
T95794: nowiki escaping should account for leading space at start-of-line in an indent-pre block
!! options
parsoid=html2wt
* bar
!! end
+!! test
+Whitespace scrubbing in SOL position should account for SOL-sensitive wikitext markup
+!! options
+parsoid = {
+ "modes": ["html2wt"],
+ "scrubWikitext": true
+}
+!! html/parsoid
+<p> foo</p>
+<p> %foo</p>
+<p> *foo</p>
+<p> #foo</p>
+<p> =foo=</p>
+<p><link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid="{}"> *foo</p>
+<p> <link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid="{}">*foo</p>
+<p> <!--boo-->*foo</p>
+<p><!--boo--> *foo</p>
+<p><!--a--> <!--b--> <!--c--> <!--d--> <!--e--> foo</p>
+<p><!--a--> <!--b--> <!--c--> <!--d--> <!--e--> *foo</p>
+!! wikitext
+foo
+
+%foo
+
+<nowiki/>*foo
+
+<nowiki/>#foo
+
+<nowiki/>=foo=
+
+[[Category:Foo]]
+<nowiki/>*foo
+
+ [[Category:Foo]]
+<nowiki>*</nowiki>foo
+
+<nowiki/><!--boo-->*foo
+
+<!--boo--><nowiki/>*foo
+
+<!--a--><!--b--><!--c--><!--d--><!--e-->foo
+
+<!--a--><nowiki/><!--b--><!--c--><!--d--><!--e-->*foo
+!! end
+
#### --------------- Behavior Switches --------------------
!! test
baz<nowiki></ref></nowiki>
!! end
+!! test
+Parsoid: newline inducing block nodes don't suppress <nowiki>
+!! options
+parsoid=html2wt
+!! html/parsoid
+ a<h1>foo</h1>
+!! wikitext
+<nowiki> </nowiki>a
+
+= foo =
+!! end
+
#### --------------- Others ---------------
!! test
Escaping nowikis
Accept empty td cell attribute
!! wikitext
{|
-| align="center" | foo || |
+| align="center" |foo|| |
|}
!! html
<table>
<tr>
-<td align="center"> foo </td>
+<td align="center">foo</td>
<td>
</td></tr></table>
Non-empty attributes in th-cells
!! wikitext
{|
-! Foo !! style="color: red" | Bar
+!Foo!! style="color: red" |Bar
|}
!! html
<table>
<tr>
-<th> Foo </th>
-<th style="color: red"> Bar
+<th>Foo</th>
+<th style="color: red">Bar
</th></tr></table>
!!end
Accept empty attributes in th-cells
!! wikitext
{|
-!| foo !!| bar
+!|foo!!|bar
|}
!! html
<table>
<tr>
-<th> foo </th>
-<th> bar
+<th>foo</th>
+<th>bar
</th></tr></table>
!!end
Empty table rows go away
!! wikitext
{|
-| Hello
-| there
+|Hello
+|there
|- class="foo"
|-
|}
!! html
<table>
<tr>
-<td> Hello
+<td>Hello
</td>
-<td> there
+<td>there
</td></tr>
</table>
!!end
-## We have some newline diffs RT-ing this edge case
-## and it is not important enough -- we seem to be emitting
-## at most 2 newlines after a </tr> and this is unrelated to
-## the issue from T85627 that this is testing.
-!!test
+!! test
Indented table with blank lines in between (T85627)
-!! options
-parsoid=wt2html
!! wikitext
{|
|foo
|}
-!! html
+!! html/php
<table>
-
<tr>
<td>foo
+<p><br />
+</p>
</td></tr></table>
-!!end
+!! html/parsoid
+ <table>
+ <tbody><tr><td>foo
+ <p>
+ <br /></p></td></tr>
+ </tbody></table>
+!! end
!!test
Indented block & table
!! wikitext
{|
<!--hi-->|-
- | there
+ |there
|}
!! html/php
<table>
<tr>
-<td> there
+<td>there
</td></tr></table>
!! html/parsoid
</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>
</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
{|
|-
|-
<!--c--> <!--d-->
|}
-!! html
+!! html/php+tidy
+<table>
+
+
+</table>
+!! html/parsoid
<table>
<tbody>
<tr class='mw-empty-elt'></tr>
!! options
parsoid=html2wt
!! html/parsoid
-<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>foo</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><p>new para</p>
+<meta typeof="mw:Includes/IncludeOnly" data-parsoid='{"src":"<includeonly>foo</includeonly>"}' data-mw='{"src":"<includeonly>foo</includeonly>"}'/><meta typeof="mw:Includes/IncludeOnly/End" data-parsoid='{"src":""}'/><p>new para</p>
<link rel="mw:PageProp/Category" href="./Category:Foo" data-parsoid='{}'/><h1>new heading</h1>
!! wikitext
<div typeof="mw:placeholder stuff" data-mw="whoo" data-parsoid="weird" data-parsoid-other="no" about="time" rel="mw:true">foo</div>
{| typeof="mw:placeholder stuff" data-mw="whoo" data-parsoid="weird" data-parsoid-other="no" about="time" rel="mw:true"
-| ok
+|ok
|}
!! html/parsoid
<div data-x-typeof="mw:placeholder stuff" data-x-data-mw="whoo" data-x-data-parsoid="weird" data-x-data-parsoid-other="no" data-x-about="time" data-x-rel="mw:true">foo</div>
<table data-x-typeof="mw:placeholder stuff" data-x-data-mw="whoo" data-x-data-parsoid="weird" data-x-data-parsoid-other="no" data-x-about="time" data-x-rel="mw:true">
-<tbody><tr><td data-parsoid='{"autoInsertedEnd":true}'> ok</td></tr>
+<tbody><tr><td data-parsoid='{"autoInsertedEnd":true}'>ok</td></tr>
</tbody></table>
!!end
## Currently the p-wrapper is fragile in how it adds / removes transformations.
## Having nested or stray pre tags results in the attempt to add duplicates,
## causing an assertion fail. This test tries to prevent that situation.
-!!test
+!! test
Ensure ParagraphWrapper can deal with stray closing pre tags
-!!options
+!! options
parsoid=wt2html
!! wikitext
plain text</pre>
!! html/parsoid
-plain text
-!!end
+<p>plain text</p>
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
1. Ensure fostered text content is wrapped in element nodes
-!!options
+!! options
parsoid=wt2html
!! wikitext
<table>hi</table><table>ho</table>
+!! html/php+tidy
+hi<table></table>ho<table></table>
!! html/parsoid
-<p>hi</p>
-<table></table>
-<p>ho</p>
-<table></table>
-!!end
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>hi</p><table data-parsoid='{"stx":"html"}'></table><p data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'>ho</p><table data-parsoid='{"stx":"html"}'></table>
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
2. Ensure fostered text content is wrapped in element nodes (traps regressions around fostered marker on the element getting lost)
-!!options
+!! options
parsoid=wt2html,wt2wt
!! wikitext
<table>
<tr> || ||
<td> a
</table>
+!! html/php+tidy
+ || ||
+<table>
+<tbody><tr><td> a
+</td></tr></tbody></table>
!! html/parsoid
-<p> || ||
-</p><table>
-<tbody><tr><td> a</td></tr>
-</tbody></table>
-!!end
+<p data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true}'> || ||</p>
+<table data-parsoid='{"stx":"html"}'>
+<tbody><tr data-parsoid='{"stx":"html","autoInsertedEnd":true}'><td data-parsoid='{"stx":"html","autoInsertedEnd":true}'> a
+</td></tr></tbody></table>
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
Encapsulation properly handles null DSR information from foster box
-!!options
+!! options
parsoid=wt2html,wt2wt
!! wikitext
{{echo|<table>foo<tr><td>bar</td></tr></table>}}
!! html/parsoid
-<span typeof="mw:Transclusion" data-mw="{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<table>foo<tr><td>bar</td></tr></table>"}},"i":0}}]}">foo</span><table><tbody><tr><td>bar</td></tr></tbody></table>
-!!end
+<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<table>foo<tr><td>bar</td></tr></table>"}},"i":0}}]}'>foo</p><table about="#mwt1" data-parsoid='{"stx":"html"}'><tbody><tr><td>bar</td></tr></tbody></table>
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
1. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
<table>{{echo|foo<tr><td>bar</td></tr>}}</table>
+!! html/php+tidy
+foo<table><tbody><tr><td>bar</td></tr></tbody></table>
!! html/parsoid
-<p typeof="mw:Transclusion" data-mw="{"parts":["<table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo<tr><td>bar</td></tr>"}},"i":0}},"</table>"]}">foo</p><table>
-<tbody>
-<tr>
-<td>bar</td>
-</tr>
-</tbody>
-</table>
-!!end
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE_html","pi":[[{"k":"1"}]]}' data-mw='{"parts":["<table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo<tr><td>bar</td></tr>"}},"i":0}},"</table>"]}'>foo</p><table about="#mwt2" data-parsoid='{"stx":"html"}'><tbody><tr><td>bar</td></tr></tbody></table>
+!! end
-!!test
+!! test
2. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
<table><div>{{echo|foo}}</div><tr><td>bar</td></tr></table>
</tr>
</tbody>
</table>
-!!end
+!! end
-!!test
+!! test
3. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
<table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
</tr>
</tbody>
</table>
-!!end
+!! end
-!!test
+!! test
4. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
<table><div><p>{{echo|foo</p></div><tr><td>}}bar</td></tr></table>
</tr>
</tbody>
</table>
-!!end
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
5. Encapsulate foster-parented transclusion content
!!options
parsoid=wt2wt,wt2html
!! wikitext
<table><tr><td><div><p>{{echo|foo</p></div></td>foo}}</tr></table>
+!! html/php+tidy
+foo<table><tbody><tr><td><div><p>foo</p></div></td></tr></tbody></table>
!! html/parsoid
-<p typeof="mw:Transclusion" data-mw="{"parts":["<table><tr><td><div><p>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo</p></div></td>foo"}},"i":0}},"</tr></table>"]}">foo</p>
-<table>
-<tbody>
-<tr>
-<td>
-<div>
-<p>foo</p>
-</div>
-</td>
-</tr>
-</tbody>
-</table>
-!!end
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE_html","pi":[[{"k":"1"}]]}' data-mw='{"parts":["<table><tr><td><div><p>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo</p></div></td>foo"}},"i":0}},"</tr></table>"]}'>foo</p><table about="#mwt2" data-parsoid='{"stx":"html"}'><tbody><tr><td><div><p>foo</p></div></td></tr></tbody></table>
+!! end
-!!test
+## Remex doesn't account for fostered content.
+!! test
6. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
<table><tr><td><div><p>{{echo|foo</p></div></td>foo</tr></table>}}<p>ok</p>
+!! html/php+tidy
+foo<table><tbody><tr><td><div><p>foo</p></div></td></tr></tbody></table><p>ok</p>
!! html/parsoid
-<p typeof="mw:Transclusion" data-mw="{"parts":["<table><tr><td><div><p>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo</p></div></td>foo</tr></table>"}},"i":0}}]}">foo</p>
-<table>
-<tbody>
-<tr>
-<td>
-<div>
-<p>foo</p>
-</div>
-</td>
-</tr>
-</tbody>
-</table>
-<p>ok</p>
-!!end
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE_html","pi":[[{"k":"1"}]]}' data-mw='{"parts":["<table><tr><td><div><p>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"foo</p></div></td>foo</tr></table>"}},"i":0}}]}'>foo</p><table about="#mwt2" data-parsoid='{"stx":"html"}'><tbody><tr><td><div><p>foo</p></div></td></tr></tbody></table><p data-parsoid='{"stx":"html"}'>ok</p>
+!! end
-!!test
+!! test
7. Encapsulate foster-parented transclusion content
!!options
parsoid=wt2wt,wt2html
</tr>
</tbody>
</table>
-!!end
+!! end
+## Remex doesn't account for fostered content.
# Note that the wt is broken on purpose: the = should be {{=}} if you
# don't want it to be a template parameter key.
-!!test
+!! test
8. Encapsulate foster-parented transclusion content
-!!options
+!! options
parsoid=wt2wt,wt2html
!! wikitext
{{echo|a
|-
|b
|}
-!! html/parsoid
-<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n"}},"i":0}}]}'>a</p>
-<span> </span>
-<p typeof="mw:Transclusion" data-mw='{"parts":["{|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"style":{"wt":"'color:red'"}},"i":0}},"\n|-\n|b\n|}"]}'>{{{1}}}</p>
+!! html/php+tidy
+<p>a
+</p>
<table>
-<tbody>
-<tr>
-<td>b</td>
-</tr>
-</tbody>
-</table>
-!!end
-!!test
+<tbody><tr>
+<td>b
+</td></tr></tbody></table>
+!! html/parsoid
+<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"a\n"}},"i":0}}]}'>a</p><span about="#mwt1">
+</span><p about="#mwt3" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE","pi":[[{"k":"style","named":true}]]}' data-mw='{"parts":["{|",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"style":{"wt":"'color:red'"}},"i":0}},"\n|-\n|b\n|}"]}'>{{{1}}}</p><table about="#mwt3">
+<tbody><tr>
+<td>b
+</td></tr></tbody></table>
+!! end
+
+## Remex doesn't account for fostered content.
+!! test
9. Encapsulate foster-parented transclusion content
!!options
parsoid=wt2wt,wt2html
!! wikitext
<table>{{echo|hi</table>hello}}
+!! html/php+tidy
+hi<table></table><p>hello
+</p>
!! html/parsoid
-<p about="#mwt2" typeof="mw:Transclusion" data-mw='{"parts":["<table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi</table>hello"}},"i":0}}]}' data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"pi":[[{"k":"1"}]]}'>hi</p><table about="#mwt2" data-parsoid='{"stx":"html"}'></table><p about="#mwt2">hello</p>
-!!end
+<p about="#mwt2" typeof="mw:Transclusion" data-parsoid='{"fostered":true,"autoInsertedEnd":true,"autoInsertedStart":true,"firstWikitextNode":"TABLE_html","pi":[[{"k":"1"}]]}' data-mw='{"parts":["<table>",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi</table>hello"}},"i":0}}]}'>hi</p><table about="#mwt2"></table><p about="#mwt2">hello</p>
+!! end
-!!test
+!! test
Table in fosterable position
!!options
parsoid=wt2html
<table>
</table>
-!!end
+!! end
# Parsoid only for T66747
!! test
</table>
!! end
+## No longer captures its original intention
!! test
Always encapsulate foster box when template range is expanded to table
!! options
+disabled
parsoid=wt2wt
!! wikitext
{|
!! 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
!! html/parsoid
<ul><li>a<br>b</li><li>c</li></ul>
!! wikitext
-* a<br>b
+* a<br />b
* c
!! end
== hi pal ==
-<!--foo--> [[Category:A3]]
+<!--foo-->[[Category:A3]]
== how goes it ==
!! html/parsoid
<a rel="mw:WikiLink" href="./Football"><i>Foot</i></a><a rel="mw:WikiLink" href="./Football"><i>ball</i></a>
!! wikitext
-[[Football|''Football'']]
+''[[Football]]''
!! end
!! test
[[Football|Foot]][[Football|ball]]
!! end
+!! test
+1. Move format tags outside of WikiLink
+!! options
+parsoid={
+ "modes": ["html2wt"],
+ "scrubWikitext": true
+}
+!! html/parsoid
+<a rel="mw:WikiLink" href="./Football"><i>Football</i></a>
+<a rel="mw:WikiLink" href="./Football"><i><b>Football</b></i></a>
+<a rel="mw:WikiLink" href="./Football"><u><i><b>Football</b></i></u></a>
+!! wikitext
+''[[Football]]''
+'''''[[Football]]'''''
+<u>'''''[[Football]]'''''</u>
+!! end
+
+!! test
+2. Move format tags outside of WikiLink with mergable A tags
+!! options
+parsoid={
+ "modes": ["html2wt"],
+ "scrubWikitext": true
+}
+!! html/parsoid
+<a rel="mw:WikiLink" href="./Football"><i><b>Foot</b></i></a><a rel="mw:WikiLink" href="./Football"><i><b>ball</b></i></a>
+!! wikitext
+'''''[[Football]]'''''
+!! end
+
+!! test
+3. Move format tags outside of WikiLink while preserving formats already outside WikiLink
+!! options
+parsoid={
+ "modes": ["html2wt"],
+ "scrubWikitext": true
+}
+!! html/parsoid
+<font color="red"><a rel="mw:WikiLink" href="./Foo" title="Foo" class="mw-redirect"><u><b>Foo</b></u></a></font>
+!! wikitext
+<font color="red"><u>'''[[Foo]]'''</u></font>
+!! end
+
+!! test
+4. Do not move format tags outside of WikiLink which includes attributes color, style and class
+!! options
+parsoid={
+ "modes": ["html2wt"],
+ "scrubWikitext": true
+}
+!! html/parsoid
+<a rel="mw:WikiLink" href="./Foo" title="Foo" class="mw-redirect"><font color="red">Foo</font></a>
+<a rel="mw:WikiLink" href="./Foo" title="Foo" class="mw-redirect"><span style="color: blue; font-size: 46px;">Foo></span></a>
+<a rel="mw:WikiLink" href="./Foo" title="Foo" class="mw-redirect"><span class="Bar">Foo</span></a>
+!! wikitext
+[[Foo|<font color="red">Foo</font>]]
+[[Foo|<span style="color: blue; font-size: 46px;">Foo></span>]]
+[[Foo|<span class="Bar">Foo</span>]]
+!! end
+
+!! test
+5. T194083 Regression test: Manual edit test that also enables scrubWikitext to move format tags outside wikilinks
+!! options
+parsoid={
+ "modes": ["selser"],
+ "scrubWikitext": true,
+ "changes": [
+ ["a", "html", "<i>Foo</i>"]
+ ]
+}
+!! wikitext
+[[Foo]]
+!! wikitext/edited
+''[[Foo]]''
+!! end
+
+!! test
+6. Regression test: Manual edit test to ensure diff markers are not lost
+!! options
+parsoid={
+ "modes": ["selser"],
+ "scrubWikitext": true,
+ "changes": [
+ ["i", "wrap", "<a href='./Foo' rel='mw:WikiLink'></a>"]
+ ]
+}
+!! wikitext
+''Foo''
+!! wikitext/edited
+''[[Foo]]''
+!! end
+
+!! test
+7. T194083 Regression test: Manual edit test to ensure nested diff markers aren't inserted
+!! options
+parsoid={
+ "modes": ["selser"],
+ "scrubWikitext": true,
+ "changes": [
+ ["div", "after", "\n<p><a href='./Foo' rel='mw:WikiLink'>Foo </a>, placeholder</p>"]
+ ]
+}
+!! wikitext
+<div>placeholder</div>
+!! wikitext/edited
+<div>placeholder</div>
+[[Foo]] , placeholder
+!! end
+
#------------------------------
# End of tag minimization tests
#------------------------------
<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><a href="/wiki/Special:BookSources/123456789X" class="internal mw-magiclink-isbn">ISBN 123456789x</a></div></div></div>
!! html/parsoid
<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a rel="mw:ExtLink" class="external free" href="http://example.com">http://example.com</a></figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a href="https://tools.ietf.org/html/rfc1234" rel="mw:ExtLink" class="external text">RFC 1234</a></figcaption></figure>
-<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external text">PMID 1234</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a href="https://tools.ietf.org/html/rfc1234" rel="mw:ExtLink" class="external mw-magiclink">RFC 1234</a></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a href="//www.ncbi.nlm.nih.gov/pubmed/1234?dopt=Abstract" rel="mw:ExtLink" class="external mw-magiclink">PMID 1234</a></figcaption></figure>
<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./File:Foobar.jpg"><img 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"/></a><figcaption><a href="./Special:BookSources/123456789X" rel="mw:WikiLink">ISBN 123456789x</a></figcaption></figure>
!! end
|<nowiki>- </nowiki>
|-
|<small>-</small>
-|<br>
--
-|<br>
+|<br />
-
+|<br />-
|}
!! html/php+tidy
<table>
<p>-
</p>
</td>
-<td><br />
-<p>-
-</p>
+<td><br />-
</td></tr></tbody></table>
!! end
!! end
!! test
-WTS change modes
+Testing serialization after deletion in references
!! options
parsoid={
"modes": ["wt2wt"],
"changes": [
- [ "#xyz", "before", "<b>before</b> stuff " ],
- [ "#xyz", "after", " stuff <i>after</i>" ],
- [ "#xyz", "html", "x <b>y</b> z" ]
+ ["#x", "remove"]
]
}
!! wikitext
-<span id="xyz">hello</span>
+hi <ref><div id="x">ho</div></ref>
+
+<references />
!! wikitext/edited
-'''before''' stuff <span id="xyz">x '''y''' z</span> stuff ''after''
-!! end
+hi <ref></ref>
-!! test
-Never serialize a-tag as html, regardless of what data-parsoid has to say
-!! options
-parsoid={ "modes": ["html2wt"], "suppressErrors": true }
-!! html/parsoid
-<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"html"}'>Foo</a>
-!! wikitext
-[[Foo]]
+<references />
!! end
-## SSS FIXME: This is broken output nevertheless.
-## What might be a reasonable non-broken output for this?
-## This is an edge case unlikely to be seen in production
-## that I am not wasting more time on this right now.
+!!test
+Testing serialization after deletion of table cells
+!!options
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ ["#x", "remove"]
+ ]
+}
+!!wikitext
+{|
+!h1 !!h2 !!h3
+| id="x" |c1 {{!}}{{!}}{{!}}c2 |||c3
+|}
+!! wikitext/edited
+{|
+!h1!!h2!!h3
+|c2|||c3
+|}
+!!end
+
!! test
-Never serialize a-tag as html, no matter what attributes it has
+Testing selser after addition of new row before first row (T125419)
!! options
-parsoid={ "modes": ["html2wt"], "suppressErrors": true }
-!! html/parsoid
-<a bad='true' href='http://boo.org'><img src='http://boohoo.org' /></a>
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ [ "tr", "before", "<tr><td>X</td></tr>" ]
+ ]
+}
!! wikitext
-[http://boo.org http://boohoo.org]
+{|
+|a
+|}
+!! wikitext/edited
+{|
+|X
+|-
+|a
+|}
!! end
-# Misnested is an indication that selser can reuse the source but these have
-# shown to sneak through on occasion. See T101768.
-# The original wikitext here is: [http://test.com [[one]] two three]
!! test
-Strip span tags added to mark misnested links
+Serialize new table rows in a HTML table using HTML tags
!! options
-parsoid=html2wt
-!! html/parsoid
-<p data-parsoid='{}'><a rel="mw:ExtLink" href="http://test.com" data-parsoid='{"targetOff":17,"contentOffsets":[17,34]}'></a><a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"simple","a":{"href":"./One"},"sa":{"href":"one"},"misnested":true}'>one</a><span data-parsoid='{"misnested":true}'> two three</span></p>
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ [ "tr", "before", "<tr><td>X</td></tr>" ]
+ ]
+}
!! wikitext
-[http://test.com][[one]] two three
+<table><tr><td>a</td></tr></table>
+!! wikitext/edited
+<table><tr><td>X</td></tr><tr><td>a</td></tr></table>
!! end
!! test
-Catch regression when unpacking misnested links
+Serialize new table cells in a HTML row using HTML tags
!! options
-parsoid=wt2html
-!! wikitext
-{{echo|hi}}[http://example.com [[ho]]]
+parsoid={
+ "modes": ["wt2wt", "selser"],
+ "changes": [
+ [ "td", "before", "<td>X</td>" ]
+ ]
+}
+!! wikitext
+<table><tr><td>a</td></tr></table>
+!! wikitext/edited
+<table><tr><td>X</td><td>a</td></tr></table>
+!! end
+
+!! test
+Serialize wikitext list items as HTML list items when embedded in a HTML list
+!! options
+parsoid=html2wt
+!! html/parsoid
+<ul data-parsoid='{"stx": "html"}'>
+<li data-parsoid='{}'>a</li>
+<li>b</li>
+</ul>
+!! wikitext
+<ul>
+<li>a</li>
+<li>b</li>
+</ul>
+!! html/php+tidy
+<ul>
+<li>a</li>
+<li>b</li>
+</ul>
+!! end
+
+# 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/parsoid
+<ul data-parsoid='{"stx": "html"}'>
+<li data-parsoid='{"stx": "html"}'>a
+<ul><li>b</li></ul>
+</li>
+</ul>
+
+<ul data-parsoid='{"stx": "html"}'>
+<li>x
+<ul><li>y</li></ul>
+</li>
+</ul>
+!! wikitext
+<ul>
+<li>a
+* b
+</li>
+</ul>
+
+<ul>
+<li>x
+* 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
+WTS change modes
+!! options
+parsoid={
+ "modes": ["wt2wt"],
+ "changes": [
+ [ "#xyz", "before", "<b>before</b> stuff " ],
+ [ "#xyz", "after", " stuff <i>after</i>" ],
+ [ "#xyz", "html", "x <b>y</b> z" ]
+ ]
+}
+!! wikitext
+<span id="xyz">hello</span>
+!! wikitext/edited
+'''before''' stuff <span id="xyz">x '''y''' z</span> stuff ''after''
+!! end
+
+!! test
+Never serialize a-tag as html, regardless of what data-parsoid has to say
+!! options
+parsoid={ "modes": ["html2wt"], "suppressErrors": true }
+!! html/parsoid
+<a rel="mw:WikiLink" href="./Foo" title="Foo" data-parsoid='{"stx":"html"}'>Foo</a>
+!! wikitext
+[[Foo]]
+!! end
+
+## SSS FIXME: This is broken output nevertheless.
+## What might be a reasonable non-broken output for this?
+## This is an edge case unlikely to be seen in production
+## that I am not wasting more time on this right now.
+!! test
+Never serialize a-tag as html, no matter what attributes it has
+!! options
+parsoid={ "modes": ["html2wt"], "suppressErrors": true }
+!! html/parsoid
+<a bad='true' href='http://boo.org'><img src='http://boohoo.org' /></a>
+!! wikitext
+[http://boo.org http://boohoo.org]
+!! end
+
+# Misnested is an indication that selser can reuse the source but these have
+# shown to sneak through on occasion. See T101768.
+# The original wikitext here is: [http://test.com [[one]] two three]
+!! test
+Strip span tags added to mark misnested links
+!! options
+parsoid=html2wt
+!! html/parsoid
+<p data-parsoid='{}'><a rel="mw:ExtLink" href="http://test.com" data-parsoid='{"targetOff":17,"contentOffsets":[17,34]}'></a><a rel="mw:WikiLink" href="./One" title="One" data-parsoid='{"stx":"simple","a":{"href":"./One"},"sa":{"href":"one"},"misnested":true}'>one</a><span data-parsoid='{"misnested":true}'> two three</span></p>
+!! wikitext
+[http://test.com][[one]] two three
+!! end
+
+!! test
+Catch regression when unpacking misnested links
+!! options
+parsoid=wt2html
+!! wikitext
+{{echo|hi}}[http://example.com [[ho]]]
!! html/parsoid
<p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi"}},"i":0}}]}'>hi</span><a rel="mw:ExtLink" class="external autonumber" href="http://example.com"></a><a rel="mw:WikiLink" href="./Ho" title="Ho" data-parsoid='{"misnested":true}'>ho</a></p>
!! end
!! html/parsoid
<h2> <link href="./Category:A2" rel="mw:PageProp/Category" />ok</h2>
!! wikitext
- [[Category:A2]]
+[[Category:A2]]
== ok ==
!! end
!! html/parsoid
<h2>foo<br/>bar</h2>
!! wikitext
-== foo<br> bar ==
+== foo<br />bar ==
!! end
!! test
"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>
"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
"modes": ["html2wt"],
"scrubWikitext": false
}
-!! html
+!! html/parsoid
<table>
<tr><td>a</td></tr>
<tr><td>-</td></tr>
<tr><td>+</td></tr>
+<tr><td>}</td></tr>
</table>
!! wikitext
{|
|<nowiki>-</nowiki>
|-
|<nowiki>+</nowiki>
+|-
+|<nowiki>}</nowiki>
|}
!! end
"modes": ["html2wt"],
"scrubWikitext": true
}
-!! html
+!! html/parsoid
<table>
<tr><td>a</td></tr>
<tr><td>-</td></tr>
<tr><td>+</td></tr>
+<tr><td>}</td></tr>
</table>
!! wikitext
{|
| -
|-
| +
+|-
+| }
|}
!! end
"modes": ["html2wt"],
"scrubWikitext": true
}
-!! html
+!! html/parsoid
<font>foo</font>
<font><font>bar</font></font>
<font class="x">boo</font>
"modes": ["html2wt"],
"scrubWikitext": false
}
-!! html
+!! html/parsoid
<font>foo</font>
!! wikitext
<font>foo</font>
}}
!! end
+!! test
+New list is serialized on newlines
+!! options
+parsoid=html2wt
+!! html/parsoid
+<p>The quick brown fox jumps over the lazy dog.</p><ul>
+<li>Yesterday</li>
+<li>Today</li>
+<li>Tomorrow</li>
+</ul><p>The quick onyx goblin jumps over the lazy dwarf.</p>
+!! wikitext
+The quick brown fox jumps over the lazy dog.
+
+* Yesterday
+* Today
+* Tomorrow
+
+The quick onyx goblin jumps over the lazy dwarf.
+!! end
+
+!! test
+New lists in formatting elements serialized w/o newlines
+!! options
+parsoid=html2wt
+!! html/parsoid
+<small>
+
+<ul>
+<li>123</li>
+</ul>
+
+</small>
+
+<small><ul><li>hi</li></ul></small>
+!! wikitext
+<small>
+* 123
+</small>
+
+<small>
+* hi
+</small>
+!! end
+
+!! test
+New list in table doesn't need newlines
+!! options
+parsoid=html2wt
+!! html/parsoid
+<table><tr><td><ul><li>test</li><li>123</li></td></tr></table>
+!! wikitext
+{|
+|
+* test
+* 123
+|}
+!! end
+
# ---------------------------------------------------
# End of tests spec'ing wikitext serialization norms |
# ---------------------------------------------------
!! test
Empty LI (T49673)
!! wikitext
-* a
+*a
*
*
-* b
+*b
!! html+tidy
-<ul><li> a</li>
-<li class="mw-empty-elt"> </li>
+<ul><li>a</li>
<li class="mw-empty-elt"></li>
-<li> b</li></ul>
+<li class="mw-empty-elt"></li>
+<li>b</li></ul>
!! end
!! test
<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: \"<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: \"<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
<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: \"<foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style>
+
+<p><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"<foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style> <link rel="foo" href="bar"/><style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"<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: \"<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: \"<foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style></p>
+
+<p>foo <style typeof="mw:Extension/style" data-mw='{"name":"style","attrs":{},"body":{"extsrc":".foo::before { content: \"<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: \"<foo>\"; }"}}'>.foo::before { content: "<foo>"; }</style>
+bar</p>
!! end
!! test
</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":["<table>\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<html><style>.hi { color: red; }</style>\n</html>"}},"i":0}},"\n<tr><td class=\"hi\">ho</td></tr>\n</table>"]}'><style typeof="mw:Extension/html" about="#mwt4" data-mw='{"name":"html","attrs":{},"body":{"extsrc":"<style>.hi { color: red; }</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
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
-== A&B&C&amp;D&amp;amp;E ==
+==A&B&C&amp;D&amp;amp;E==
[[#A&B&C&amp;D&amp;amp;E]]
!! html/php
<h2><span id="A.26B.26C.26amp.3BD.26amp.3Bamp.3BE"></span><span class="mw-headline" id="A&B&C&amp;D&amp;amp;E">A&B&C&amp;D&amp;amp;E</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: A&B&C&amp;D&amp;amp;E">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p><a href="#A&B&C&amp;D&amp;amp;E">#A&B&C&amp;D&amp;amp;E</a>
</p>
!! html/parsoid
-<h2 id="A&B&C&amp;D&amp;amp;E"><span id="A.26B.26C.26amp.3BD.26amp.3Bamp.3BE" typeof="mw:FallbackId" data-parsoid="{}"></span> A&B<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>C<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>amp;D<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>amp;amp;E </h2>
-<p><a rel="mw:WikiLink" href="./Main_Page#A&B&C&amp;D&amp;amp;E" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#A&B&C&amp;D&amp;amp;E"},"sa":{"href":"#A&B&amp;C&amp;amp;D&amp;amp;amp;E"}}'>#A&B&C&amp;D&amp;amp;E</a></p>
+<h2 id="A&B&C&amp;D&amp;amp;E"><span id="A.26B.26C.26amp.3BD.26amp.3Bamp.3BE" typeof="mw:FallbackId" data-parsoid="{}"></span>A&B<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>C<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>amp;D<span typeof="mw:Entity" data-parsoid='{"src":"&amp;","srcContent":"&"}'>&</span>amp;amp;E</h2>
+<p><a rel="mw:WikiLink" href="./Parser_test#A&B&C&amp;D&amp;amp;E" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#A&B&C&amp;D&amp;amp;E"},"sa":{"href":"#A&B&amp;C&amp;amp;D&amp;amp;amp;E"}}'>#A&B&C&amp;D&amp;amp;E</a></p>
!! end
!! test
!! config
wgFragmentMode=[ 'legacy' ]
!! wikitext
-== A&B&C&amp;D&amp;amp;E ==
+==A&B&C&amp;D&amp;amp;E==
[[#A&B&C&amp;D&amp;amp;E]]
!! html/php
<h2><span class="mw-headline" id="A.26B.26C.26amp.3BD.26amp.3Bamp.3BE">A&B&C&amp;D&amp;amp;E</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: A&B&C&amp;D&amp;amp;E">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
-== Foo bar ==
+==Foo bar==
-== foo Bar ==
+==foo Bar==
-== Тест ==
+==Тест==
-== Тест ==
+==Тест==
-== тест ==
+==тест==
-== Hey < # " > % : ' ==
+==Hey < # " > % : '==
[[#Foo bar]] [[#foo Bar]] [[#Тест]] [[#тест]] [[#Hey < # " > % : ']]
{{anchorencode:💩}} <span id="{{anchorencode:💩}}"></span>
[[#啤酒]] [[#%E5%95%A4%E9%85%92]]
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Foo_bar"><span class="tocnumber">1</span> <span class="toctext">Foo bar</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext">foo Bar</span></a></li>
</p><p><a href="#啤酒">#啤酒</a> <a href="#啤酒">#啤酒</a>
</p>
!! html/parsoid
-<h2 id="Foo_bar"> Foo bar </h2>
+<h2 id="Foo_bar">Foo bar</h2>
-<h2 id="foo_Bar_2"> foo Bar </h2>
+<h2 id="foo_Bar_2">foo Bar</h2>
-<h2 id="Тест"><span id=".D0.A2.D0.B5.D1.81.D1.82" typeof="mw:FallbackId"></span> Тест </h2>
+<h2 id="Тест"><span id=".D0.A2.D0.B5.D1.81.D1.82" typeof="mw:FallbackId"></span>Тест</h2>
-<h2 id="Тест_2"><span id=".D0.A2.D0.B5.D1.81.D1.82_2" typeof="mw:FallbackId"></span> Тест </h2>
+<h2 id="Тест_2"><span id=".D0.A2.D0.B5.D1.81.D1.82_2" typeof="mw:FallbackId"></span>Тест</h2>
-<h2 id="тест"><span id=".D1.82.D0.B5.D1.81.D1.82" typeof="mw:FallbackId"></span> тест </h2>
+<h2 id="тест"><span id=".D1.82.D0.B5.D1.81.D1.82" typeof="mw:FallbackId"></span>тест</h2>
-<h2 id="Hey_<_#_"_>_%_:_'"><span id="Hey_.3C_.23_.22_.3E_.25_:_.27" typeof="mw:FallbackId"></span> Hey < # " > %<span typeof="mw:DisplaySpace mw:Placeholder" data-parsoid='{"src":" ","isDisplayHack":true}'> </span>: ' </h2>
-<p><a rel="mw:WikiLink" href="./Main_Page#Foo_bar">#Foo bar</a> <a rel="mw:WikiLink" href="./Main_Page#foo_Bar">#foo Bar</a> <a rel="mw:WikiLink" href="./Main_Page#Тест">#Тест</a> <a rel="mw:WikiLink" href="./Main_Page#тест">#тест</a> <a rel="mw:WikiLink" href="./Main_Page#Hey_<_#_"_>_%_:_'" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Hey_<_#_\"_>_%_:_'"},"sa":{"href":"#Hey < # \" > % : '"}}'>#Hey < # " > % : '</a></p>
+<h2 id="Hey_<_#_"_>_%_:_'"><span id="Hey_.3C_.23_.22_.3E_.25_:_.27" typeof="mw:FallbackId"></span>Hey < # " > %<span typeof="mw:DisplaySpace mw:Placeholder" data-parsoid='{"src":" ","isDisplayHack":true}'> </span>: '</h2>
+<p><a rel="mw:WikiLink" href="./Parser_test#Foo_bar">#Foo bar</a> <a rel="mw:WikiLink" href="./Parser_test#foo_Bar">#foo Bar</a> <a rel="mw:WikiLink" href="./Parser_test#Тест">#Тест</a> <a rel="mw:WikiLink" href="./Parser_test#тест">#тест</a> <a rel="mw:WikiLink" href="./Parser_test#Hey_<_#_"_>_%_:_'" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Hey_<_#_\"_>_%_:_'"},"sa":{"href":"#Hey < # \" > % : '"}}'>#Hey < # " > % : '</a></p>
-<p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"anchorencode:💩","function":"anchorencode"},"params":{},"i":0}}]}'>💩</span> <span id="💩" about="#mwt3" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"id"},{"html":"<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[190,209,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:💩\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>💩</span>"}]]}'></span></p>
+<p><span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"anchorencode:💩","function":"anchorencode"},"params":{},"i":0}}]}'>💩</span> <span id="💩" about="#mwt3" typeof="mw:ExpandedAttrs" data-mw='{"attribs":[[{"txt":"id"},{"html":"<span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-parsoid='{\"pi\":[[]],\"dsr\":[178,197,null,null]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:💩\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>💩</span>"}]]}'></span></p>
<!-- These two links should produce identical HTML -->
-<p><a rel="mw:WikiLink" href="./Main_Page#啤酒">#啤酒</a> <a rel="mw:WikiLink" href="./Main_Page#啤酒" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#啤酒"},"sa":{"href":"#%E5%95%A4%E9%85%92"}}'>#啤酒</a></p>
+<p><a rel="mw:WikiLink" href="./Parser_test#啤酒">#啤酒</a> <a rel="mw:WikiLink" href="./Parser_test#啤酒" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#啤酒"},"sa":{"href":"#%E5%95%A4%E9%85%92"}}'>#啤酒</a></p>
!! end
# Parsoid doesn't support this mode
!! config
wgFragmentMode=[ 'legacy', 'html5' ]
!! wikitext
-== Foo bar ==
+==Foo bar==
-== foo Bar ==
+==foo Bar==
-== Тест ==
+==Тест==
-== Тест ==
+==Тест==
-== тест ==
+==тест==
-== Hey < # " > % : ' ==
+==Hey < # " > % : '==
[[#Foo bar]] [[#foo Bar]] [[#Тест]] [[#тест]] [[#Hey < # " > % : ']]
{{anchorencode:💩}} <span id="{{anchorencode:💩}}"></span>
[[#啤酒]] [[#%E5%95%A4%E9%85%92]]
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Foo_bar"><span class="tocnumber">1</span> <span class="toctext">Foo bar</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext">foo Bar</span></a></li>
!! config
wgFragmentMode=[ 'html5' ]
!! wikitext
-== Foo bar ==
+==Foo bar==
-== foo Bar ==
+==foo Bar==
-== Тест ==
+==Тест==
-== Тест ==
+==Тест==
-== тест ==
+==тест==
-== Hey < # " > % : ' ==
+==Hey < # " > % : '==
[[#Foo bar]] [[#foo Bar]] [[#Тест]] [[#тест]] [[#Hey < # " > % : ']]
{{anchorencode:💩}} <span id="{{anchorencode:💩}}"></span>
[[#啤酒]] [[#%E5%95%A4%E9%85%92]]
!! html/php
-<div id="toc" class="toc"><div class="toctitle" lang="en" dir="ltr"><h2>Contents</h2></div>
+<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="#Foo_bar"><span class="tocnumber">1</span> <span class="toctext">Foo bar</span></a></li>
<li class="toclevel-1 tocsection-2"><a href="#foo_Bar_2"><span class="tocnumber">2</span> <span class="toctext">foo Bar</span></a></li>
!! config
wgFragmentMode=[ 'html5', 'legacy' ]
!! wikitext
-== Foo bar ==
+==Foo bar==
[[#Foo bar]]
!! html/php
<h2><span class="mw-headline" id="Foo_bar">Foo bar</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: Foo bar">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
<p><a href="#Foo_bar">#Foo bar</a>
</p>
+!! html/parsoid
+<h2 id="Foo_bar"> Foo<span typeof="mw:Entity" data-parsoid='{"src":"&nbsp;","srcContent":" "}'> </span>bar </h2>
+<p><a rel="mw:WikiLink" href="./Parser_test#Foo_bar" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#Foo_bar"},"sa":{"href":"#Foo&nbsp;bar"}}'>#Foo bar</a></p>
!! end
!! test
<a rel="mw:WikiLink" href="./Foo" title="Foo">link <span title="title with [[double brackets]]" data-parsoid='{"stx":"html","a":{"title":"title with [[double brackets]]"},"sa":{"title":"title with &#91;&#91;double brackets&#93;&#93;"}}'>span</span></a></p>
!! end
+!! test
+T199926: html arrow wt: Parsoid sometimes trips up on verticalbar chars in hrefs
+!! options
+parsoid={
+ "modes": ["html2wt"]
+}
+!! html/parsoid
+<a href="https://stats.wikimedia.org/v2/#/fr.wikipedia.org/reading/page-views-by-country/normal|map|2-Year~2016060100~2018071100|~total">9</a>
+<a href="https://stats.wikimedia.org/v2/#/fr.wikipedia.org/reading/page-views-by-country/normal%7Cmap%7C2-Year~2016060100~2018071100%7C~total">10</a>
+!! wikitext
+[https://stats.wikimedia.org/v2/#/fr.wikipedia.org/reading/page-views-by-country/normal|map|2-Year~2016060100~2018071100|~total 9]
+[[stats:v2/#/fr.wikipedia.org/reading/page-views-by-country/normal%7Cmap%7C2-Year~2016060100~2018071100%7C~total|10]]
+!! end
+
!! test
T179544: {{anchorencode:}} output should be always usable in links
!! config
<p><span id="[foo]"></span><a href="#[foo]">#[foo]</a>
</p>
!! html/parsoid
-<p><span id="[foo]" about="#mwt3" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html","a":{"id":"[foo]"},"sa":{"id":"{{anchorencode:[foo]}}"}}' data-mw='{"attribs":[[{"txt":"id"},{"html":"<span typeof=\"mw:Transclusion mw:Entity\" about=\"#mwt1\" data-parsoid='{\"srcContent\":\"[\",\"dsr\":[10,32,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:[foo]\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>[</span><span about=\"#mwt1\" data-parsoid=\"{}\">foo</span><span typeof=\"mw:Entity\" about=\"#mwt1\" data-parsoid='{\"src\":\"&amp;#x5D;\",\"srcContent\":\"]\"}'>]</span>"}]]}'></span><a typeof="mw:ExpandedAttrs" about="#mwt4" rel="mw:WikiLink" href="./Main_Page#[foo]" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#[foo]"},"sa":{"href":"#{{anchorencode:[foo]}}"}}' data-mw='{"attribs":[[{"txt":"href"},{"html":"#<span typeof=\"mw:Transclusion mw:Entity\" about=\"#mwt2\" data-parsoid='{\"srcContent\":\"[\",\"dsr\":[44,66,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:[foo]\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>[</span><span about=\"#mwt2\" data-parsoid=\"{}\">foo</span><span typeof=\"mw:Entity\" about=\"#mwt2\" data-parsoid='{\"src\":\"&amp;#x5D;\",\"srcContent\":\"]\"}'>]</span>"}]]}'>#[foo]</a></p>
+<p><span id="[foo]" about="#mwt3" typeof="mw:ExpandedAttrs" data-parsoid='{"stx":"html","a":{"id":"[foo]"},"sa":{"id":"{{anchorencode:[foo]}}"}}' data-mw='{"attribs":[[{"txt":"id"},{"html":"<span typeof=\"mw:Transclusion mw:Entity\" about=\"#mwt1\" data-parsoid='{\"srcContent\":\"[\",\"dsr\":[10,32,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:[foo]\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>[</span><span about=\"#mwt1\" data-parsoid=\"{}\">foo</span><span typeof=\"mw:Entity\" about=\"#mwt1\" data-parsoid='{\"src\":\"&amp;#x5D;\",\"srcContent\":\"]\"}'>]</span>"}]]}'></span><a typeof="mw:ExpandedAttrs" about="#mwt4" rel="mw:WikiLink" href="./Parser_test#[foo]" data-parsoid='{"stx":"simple","a":{"href":"./Parser_test#[foo]"},"sa":{"href":"#{{anchorencode:[foo]}}"}}' data-mw='{"attribs":[[{"txt":"href"},{"html":"#<span typeof=\"mw:Transclusion mw:Entity\" about=\"#mwt2\" data-parsoid='{\"srcContent\":\"[\",\"dsr\":[44,66,null,null],\"pi\":[[]]}' data-mw='{\"parts\":[{\"template\":{\"target\":{\"wt\":\"anchorencode:[foo]\",\"function\":\"anchorencode\"},\"params\":{},\"i\":0}}]}'>[</span><span about=\"#mwt2\" data-parsoid=\"{}\">foo</span><span typeof=\"mw:Entity\" about=\"#mwt2\" data-parsoid='{\"src\":\"&amp;#x5D;\",\"srcContent\":\"]\"}'>]</span>"}]]}'>#[foo]</a></p>
!! end
## ------------------------------
"wrapSections": true
}
!! wikitext
-= 1 =
+=1=
a
-= 2 =
+=2=
b
-== 2.1 ==
+==2.1==
c
-== 2.2 ==
+==2.2==
d
-=== 2.2.1 ===
+===2.2.1===
e
-= 3 =
+=3=
f
!! html/parsoid
-<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-</section><section data-mw-section-id="2"><h1 id="2"> 2 </h1>
+</section><section data-mw-section-id="2"><h1 id="2">2</h1>
<p>b</p>
-<section data-mw-section-id="3"><h2 id="2.1"> 2.1 </h2>
+<section data-mw-section-id="3"><h2 id="2.1">2.1</h2>
<p>c</p>
-</section><section data-mw-section-id="4"><h2 id="2.2"> 2.2 </h2>
+</section><section data-mw-section-id="4"><h2 id="2.2">2.2</h2>
<p>d</p>
-<section data-mw-section-id="5"><h3 id="2.2.1"> 2.2.1 </h3>
+<section data-mw-section-id="5"><h3 id="2.2.1">2.2.1</h3>
<p>e</p>
-</section></section></section><section data-mw-section-id="6"><h1 id="3"> 3 </h1>
+</section></section></section><section data-mw-section-id="6"><h1 id="3">3</h1>
<p>f</p>
</section>
Para 3.
-= 1 =
+=1=
a
-= 2 =
+=2=
b
-== 2.1 ==
+==2.1==
c
!! html/parsoid
<section data-mw-section-id="0"><p>Para 1.</p>
<p>Para 3.</p>
-</section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+</section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-</section><section data-mw-section-id="2"><h1 id="2"> 2 </h1>
+</section><section data-mw-section-id="2"><h1 id="2">2</h1>
<p>b</p>
-<section data-mw-section-id="3"><h2 id="2.1"> 2.1 </h2>
+<section data-mw-section-id="3"><h2 id="2.1">2.1</h2>
<p>c</p>
</section></section>
"wrapSections": true
}
!! wikitext
-= 1 =
+=1=
a
{{echo|1=
-== 1.1 ==
+==1.1==
b
}}
-== 1.2 ==
+==1.2==
c
-= 2 =
+=2=
d
!! html/parsoid
-<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.1" data-parsoid='{"dsr":[9,33,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"== 1.1 ==\nb"}},"i":0}}]}'> 1.1 </h2><span about="#mwt1">
+<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.1" data-parsoid='{"dsr":[9,33,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"==1.1==\nb"}},"i":0}}]}'>1.1</h2><span about="#mwt1">
</span><p about="#mwt1">b</p>
-</section><section data-mw-section-id="3"><h2 id="1.2"> 1.2 </h2>
+</section><section data-mw-section-id="3"><h2 id="1.2">1.2</h2>
<p>c</p>
-</section></section><section data-mw-section-id="4"><h1 id="2"> 2 </h1>
+</section></section><section data-mw-section-id="4"><h1 id="2">2</h1>
<p>d</p></section>
!! end
"modes": ["wt2html", "wt2wt"]
}
!! wikitext
-= 1 =
+=1=
a
{{echo|1=
-== 1.1 ==
+==1.1==
b
-=== 1.1.1 ===
+===1.1.1===
d
}}
-= 2 =
+=2=
e
!! html/parsoid
-<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.1" data-parsoid='{"dsr":[9,50,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"== 1.1 ==\nb\n=== 1.1.1 ===\nd"}},"i":0}},"\n"]}'> 1.1 </h2><span about="#mwt1">
+<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.1" data-parsoid='{"dsr":[9,50,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"==1.1==\nb\n===1.1.1===\nd"}},"i":0}},"\n"]}'>1.1</h2><span about="#mwt1">
</span><p about="#mwt1">b</p><span about="#mwt1">
-</span><section data-mw-section-id="-1" about="#mwt1"><h3 about="#mwt1" id="1.1.1"> 1.1.1 </h3><span about="#mwt1">
+</span><section data-mw-section-id="-1" about="#mwt1"><h3 about="#mwt1" id="1.1.1">1.1.1</h3><span about="#mwt1">
</span><p about="#mwt1">d</p><span about="#mwt1">
-</span></section></section></section><section data-mw-section-id="4" data-parsoid="{}"><h1 id="2"> 2 </h1>
+</span></section></section></section><section data-mw-section-id="4" data-parsoid="{}"><h1 id="2">2</h1>
<p>e</p></section>
!! end
"modes": ["wt2html", "wt2wt"]
}
!! wikitext
-= 1 =
+=1=
a
{{echo|1=
x
-== 1.1 ==
+==1.1==
b
==1.2==
c
===1.2.1===
d
}}
-= 2 =
+=2=
e
!! html/parsoid
<section data-mw-section-id="0"></section><section data-mw-section-id="1" data-parsoid="{}"><h1 id="1"> 1 </h1>
<p>a</p>
-<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"dsr":[9,60,0,0],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"x\n== 1.1 ==\nb\n==1.2==\nc\n===1.2.1===\nd"}},"i":0}},"\n"]}'>x</p><span about="#mwt1">
-</span><section data-mw-section-id="-1" about="#mwt1"><h2 about="#mwt1" id="1.1"> 1.1 </h2><span about="#mwt1">
+<p about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"dsr":[9,60,0,0],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"x\n==1.1==\nb\n==1.2==\nc\n===1.2.1===\nd"}},"i":0}},"\n"]}'>x</p><span about="#mwt1">
+</span><section data-mw-section-id="-1" about="#mwt1"><h2 about="#mwt1" id="1.1">1.1</h2><span about="#mwt1">
</span><p about="#mwt1">b</p><span about="#mwt1">
</span></section><section data-mw-section-id="-1" about="#mwt1"><h2 about="#mwt1" id="1.2">1.2</h2><span about="#mwt1">
</span><p about="#mwt1">c</p><span about="#mwt1">
</span><section data-mw-section-id="-1" about="#mwt1"><h3 about="#mwt1" id="1.2.1">1.2.1</h3><span about="#mwt1">
</span><p about="#mwt1">d</p><span about="#mwt1">
-</span></section></section></section><section data-mw-section-id="5"><h1 id="2"> 2 </h1>
+</span></section></section></section><section data-mw-section-id="5"><h1 id="2">2</h1>
<p>e</p></section>
!! end
a
{{echo|
-= 1 =
+=1=
b
}}
<section data-mw-section-id="-1"></section><section data-mw-section-id="-2"><div data-parsoid='{"stx":"html"}'>
<p>a</p>
-<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"\n= 1 =\nb\n"}},"i":0}},"\n\nc\n"]}'>
-</span><section data-mw-section-id="-1" about="#mwt1"><h1 about="#mwt1" id="1"> 1 </h1><span about="#mwt1">
+<span about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"\n=1=\nb\n"}},"i":0}},"\n\nc\n"]}'>
+</span><section data-mw-section-id="-1" about="#mwt1"><h1 about="#mwt1" id="1">1</h1><span about="#mwt1">
</span><p about="#mwt1">b
</p><span about="#mwt1">
"wrapSections": true
}
!! wikitext
-= 1 =
+=1=
a
{{echo|1=
-= 2 =
+=2=
b
-== 2.1 ==
+==2.1==
c
}}
d
-= 3 =
+=3=
e
!! html/parsoid
-<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+<section data-mw-section-id="0"></section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-</section><section data-mw-section-id="-1"><h1 about="#mwt1" typeof="mw:Transclusion" id="2" data-parsoid='{"dsr":[9,45,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"= 2 =\nb\n== 2.1 ==\nc"}},"i":0}},"\n\nd\n\n"]}'> 2 </h1><span about="#mwt1">
+</section><section data-mw-section-id="-1"><h1 about="#mwt1" typeof="mw:Transclusion" id="2" data-parsoid='{"dsr":[9,45,null,null],"pi":[[{"k":"1","named":true,"spc":["","","\n","\n"]}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"=2=\nb\n==2.1==\nc"}},"i":0}},"\n\nd\n\n"]}'>2</h1><span about="#mwt1">
</span><p about="#mwt1">b</p><span about="#mwt1">
-</span><section data-mw-section-id="-1" about="#mwt1"><h2 about="#mwt1" id="2.1"> 2.1 </h2><span about="#mwt1">
+</span><section data-mw-section-id="-1" about="#mwt1"><h2 about="#mwt1" id="2.1">2.1</h2><span about="#mwt1">
</span><p about="#mwt1">c</p><span about="#mwt1">
</span><p about="#mwt1">d</p><span about="#mwt1">
-</span></section></section><section data-mw-section-id="4"><h1 id="3"> 3 </h1>
+</span></section></section><section data-mw-section-id="4"><h1 id="3">3</h1>
<p>e</p></section>
!! end
"modes": ["wt2html", "wt2wt"]
}
!! wikitext
-= 1 =
+=1=
a
{{echo|1=
-== 1.2 ==
+==1.2==
b
-= 2 =
+=2=
c
}}
d
-= 3 =
+=3=
e
!! html/parsoid
-<section data-mw-section-id="0"></section><section data-mw-section-id="1" about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["= 1 =\na\n\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"== 1.2 ==\nb\n= 2 =\nc"}},"i":0}},"\n\nd\n\n"]}'><h1 id="1"> 1 </h1>
+<section data-mw-section-id="0"></section><section data-mw-section-id="1" about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":["=1=\na\n\n",{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"==1.2==\nb\n=2=\nc"}},"i":0}},"\n\nd\n\n"]}'><h1 id="1">1</h1>
<p>a</p>
-<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.2" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"== 1.2 ==\nb\n= 2 =\nc"}},"i":0}}]}'> 1.2 </h2><span about="#mwt1">
+<section data-mw-section-id="-1"><h2 about="#mwt1" typeof="mw:Transclusion" id="1.2" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"==1.2==\nb\n=2=\nc"}},"i":0}}]}'>1.2</h2><span about="#mwt1">
</span><p about="#mwt1">b</p><span about="#mwt1">
-</span></section></section><section data-mw-section-id="-1" about="#mwt1"><h1 about="#mwt1" id="2"> 2 </h1><span about="#mwt1">
+</span></section></section><section data-mw-section-id="-1" about="#mwt1"><h1 about="#mwt1" id="2">2</h1><span about="#mwt1">
</span><p about="#mwt1">c</p>
<p>d</p>
-</section><section data-mw-section-id="4" data-parsoid="{}"><h1 id="3"> 3 </h1>
+</section><section data-mw-section-id="4" data-parsoid="{}"><h1 id="3">3</h1>
<p>e</p></section>
!! end
foo
<div style="border:1px solid red;">
-= 1 =
+=1=
a
-== 1.1 ==
+==1.1==
b
-= 2 =
+=2=
c
</div>
-= 3 =
+=3=
d
-== 3.1 ==
+==3.1==
e
!! html/parsoid
<section data-mw-section-id="-1"><p>foo</p>
</section><section data-mw-section-id="-2"><div style="border:1px solid red;">
-<section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+<section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-<section data-mw-section-id="2"><h2 id="1.1"> 1.1 </h2>
+<section data-mw-section-id="2"><h2 id="1.1">1.1</h2>
<p>b</p>
-</section></section><section data-mw-section-id="-1"><h1 id="2"> 2 </h1>
+</section></section><section data-mw-section-id="-1"><h1 id="2">2</h1>
<p>c</p>
</section></div>
-</section><section data-mw-section-id="4"><h1 id="3"> 3 </h1>
+</section><section data-mw-section-id="4"><h1 id="3">3</h1>
<p>d</p>
-<section data-mw-section-id="5"><h2 id="3.1"> 3.1 </h2>
+<section data-mw-section-id="5"><h2 id="3.1">3.1</h2>
<p>e</p>
</section></section>
!! end
!! wikitext
foo
-= 1 =
+=1=
a
<div style="border:1px solid red;">
b
-== 1.1 ==
+==1.1==
c
-= 2 =
+=2=
d
</div>
e
-= 3 =
+=3=
f
-== 3.1 ==
+==3.1==
g
!! html/parsoid
<section data-mw-section-id="0"><p>foo</p>
-</section><section data-mw-section-id="-1"><h1 id="1"> 1 </h1>
+</section><section data-mw-section-id="-1"><h1 id="1">1</h1>
<p>a</p>
</section><section data-mw-section-id="-2"><div style="border:1px solid red;">
<p>b</p>
-<section data-mw-section-id="2"><h2 id="1.1"> 1.1 </h2>
+<section data-mw-section-id="2"><h2 id="1.1">1.1</h2>
<p>c</p>
-</section><section data-mw-section-id="-1"><h1 id="2"> 2 </h1>
+</section><section data-mw-section-id="-1"><h1 id="2">2</h1>
<p>d</p>
</section></div>
<p>e</p>
-</section><section data-mw-section-id="4"><h1 id="3"> 3 </h1>
+</section><section data-mw-section-id="4"><h1 id="3">3</h1>
<p>f</p>
-<section data-mw-section-id="5"><h2 id="3.1"> 3.1 </h2>
+<section data-mw-section-id="5"><h2 id="3.1">3.1</h2>
<p>g</p>
</section></section>
!! end
<h1>a</h1>
-= b =
+=b=
<h1>c</h1>
-= d =
+=d=
!! html/parsoid
<section data-mw-section-id="0"><p>foo</p>
<h1 id="a" data-parsoid='{"stx":"html"}'>a</h1>
-</section><section data-mw-section-id="1"><h1 id="b"> b </h1>
+</section><section data-mw-section-id="1"><h1 id="b">b</h1>
<h1 id="c" data-parsoid='{"stx":"html"}'>c</h1>
-</section><section data-mw-section-id="2"><h1 id="d"> d </h1></section>
+</section><section data-mw-section-id="2"><h1 id="d">d</h1></section>
!! end
!! test
!! wikitext
<!-- this is a comment, presumably significant to editors -->
-= 1 =
+=1=
a
-= 2 =
+=2=
b
!! html/parsoid
<section data-mw-section-id="0" data-parsoid="{}">
<!-- this is a comment, presumably significant to editors -->
-</section><section data-mw-section-id="1"><h1 id="1"> 1 </h1>
+</section><section data-mw-section-id="1"><h1 id="1">1</h1>
<p>a</p>
-</section><section data-mw-section-id="2"><h1 id="2"> 2 </h1>
+</section><section data-mw-section-id="2"><h1 id="2">2</h1>
<p>b</p></section>
!! end
!! wikitext
foo
{{echo|<div>
-== a ==
-== b ==
+==a==
+==b==
</div>
}}
!! html/parsoid
<section data-mw-section-id="-1"><p>foo</p>
-</section><section data-mw-section-id="-2"><div about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>\n== a ==\n== b ==\n</div>\n"}},"i":0}}]}'>
-<section data-mw-section-id="-1"><h2 id="a"> a </h2>
-</section><section data-mw-section-id="-1"><h2 id="b"> b </h2>
+</section><section data-mw-section-id="-2"><div about="#mwt1" typeof="mw:Transclusion" data-parsoid='{"stx":"html","pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"<div>\n==a==\n==b==\n</div>\n"}},"i":0}}]}'>
+<section data-mw-section-id="-1"><h2 id="a">a</h2>
+</section><section data-mw-section-id="-1"><h2 id="b">b</h2>
</section></div><span about="#mwt1">
</span></section>
!! end
+
+##########################################################################
+Tests demonstrating white-space insensitivity in input wikitext
+for wikitext headings, wikitext list items, and wikitext table captions,
+headings, and cells. HTML versions of the same should preserve whitespace.
+##########################################################################
+!! test
+Trim whitespace in wikitext headings, list items, table captions, headings, and cells
+!! options
+parsoid={
+ "modes": ["wt2html"],
+ "preserveIEW": true
+}
+!! wikitext
+__NOTOC__
+== <!--c1--> <!--c2--> Spaces <!--c3--> <!--c4--> ==
+== <!--c1--> <!--c2--> Tabs <!--c3--><!--c4--> ==
+== <!--Headings with fallback ids--> Личная жизнь ==
+* <!--c1--> <!--c2--> List item <!--c3--> <!--c4-->
+; <!--term to define--> term : <!--term's definition--> definition
+{|
+|+ <!--c1--> <!--c2--> Table Caption <!--c3--> <!--c4-->
+|-
+! <!--c1--> <!--c2--> Table Heading 1 <!--c3--> <!--c4--> !! Table Heading 2 <!--c5-->
+|-
+| <!--c1--> <!--c2--> Table Cell 1 <!--c3--> <!--c4--> || Table Cell 2 <!--c5-->
+|-
+| class="foo" || <!--c1--> <!--c2--> Table Cell 3 <!--c3--> <!--c4-->
+|-
+| <!--c1--> testing [[one|two]] <!--c2--> | <!--c3--> some content
+|}
+: {|
+ | <!--c1--> <!--c2--> Table Cell 1 <!--c3--> <!--c4--> || Table Cell 2 <!--c5-->
+ |} foo <!--c1-->
+!! html/php+tidy
+<h2><span class="mw-headline" id="Spaces">Spaces</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=1" title="Edit section: Spaces">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id="Tabs">Tabs</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=2" title="Edit section: Tabs">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<h2><span class="mw-headline" id=".D0.9B.D0.B8.D1.87.D0.BD.D0.B0.D1.8F_.D0.B6.D0.B8.D0.B7.D0.BD.D1.8C">Личная жизнь</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&action=edit&section=3" title="Edit section: Личная жизнь">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+<ul><li>List item</li></ul>
+<dl><dt>term </dt>
+<dd>definition</dd></dl>
+<table>
+<caption>Table Caption
+</caption>
+<tbody><tr>
+<th>Table Heading 1</th>
+<th>Table Heading 2
+</th></tr>
+<tr>
+<td>Table Cell 1</td>
+<td>Table Cell 2
+</td></tr>
+<tr>
+<td>class="foo"</td>
+<td>Table Cell 3
+</td></tr>
+<tr>
+<td>testing <a href="/index.php?title=One&action=edit&redlink=1" class="new" title="One (page does not exist)">two</a> | some content
+</td></tr></tbody></table>
+<dl><dd><table>
+<tbody><tr>
+<td>Table Cell 1</td>
+<td>Table Cell 2
+</td></tr></tbody></table> foo</dd></dl>
+!! html/parsoid
+<meta property="mw:PageProp/notoc">
+<h2 id="Spaces"><!--c1--><!--c2-->Spaces<!--c3--><!--c4--></h2>
+<h2 id="Tabs"><!--c1--><!--c2-->Tabs<!--c3--><!--c4--></h2>
+<h2 id="Личная_жизнь"><span id=".D0.9B.D0.B8.D1.87.D0.BD.D0.B0.D1.8F_.D0.B6.D0.B8.D0.B7.D0.BD.D1.8C" typeof="mw:FallbackId"></span><!--Headings with fallback ids-->Личная жизнь</h2>
+<ul><li><!--c1--><!--c2-->List item<!--c3--><!--c4--></li></ul>
+<dl><dt><!--term to define-->term </dt><dd><!--term's definition-->definition</dd></dl>
+<table>
+<caption><!--c1--><!--c2-->Table Caption<!--c3--><!--c4--></caption>
+<tbody><tr>
+<th><!--c1--><!--c2-->Table Heading 1<!--c3--><!--c4--></th><th>Table Heading 2<!--c5--></th></tr>
+<tr>
+<td><!--c1--><!--c2-->Table Cell 1<!--c3--><!--c4--></td><td>Table Cell 2<!--c5--></td></tr>
+<tr>
+<td>class="foo"</td><td><!--c1--><!--c2-->Table Cell 3<!--c3--><!--c4--></td></tr>
+<tr>
+<td><!--c1-->testing <a rel="mw:WikiLink" href="./One" title="One">two</a> <!--c2--> | <!--c3--> some content</td></tr>
+</tbody></table>
+<dl><dd><table>
+ <tbody><tr><td><!--c1--><!--c2-->Table Cell 1<!--c3--><!--c4--></td><td>Table Cell 2<!--c5--></td></tr>
+ </tbody></table> foo<!--c1--></dd></dl>
+!! end
+
+# Looks like <caption> is not accepted in HTML
+!! test
+Do not trim whitespace in HTML headings, list items, table captions, headings, and cells
+!! options
+parsoid={
+ "modes": ["wt2html"],
+ "preserveIEW": true
+}
+!! wikitext
+__NOTOC__
+<h2> <!--c1--> <!--c2--> Heading <!--c3--> <!--c4--> </h2>
+<ul><li> <!--c1--> <!--c2--> List item <!--c3--> <!--c4--> </li></ul>
+<table>
+<tr><th> <!--c1--> <!--c2--> Table Heading <!--c3--> <!--c4--> <th></tr>
+<tr><td> <!--c1--> <!--c2--> Table Cell <!--c3--> <!--c4--> <th></tr>
+</table>
+!! html/php+tidy
+<h2><span class="mw-headline" id="Heading"> Heading </span></h2>
+<ul><li> List item </li></ul>
+<table>
+<tbody><tr><th> Table Heading </th><th></th></tr>
+<tr><td> Table Cell </td><th></th></tr>
+</tbody></table>
+!! html/parsoid
+<meta property="mw:PageProp/notoc"/>
+<h2 id="Heading"> <!--c1--> <!--c2--> Heading <!--c3--> <!--c4--> </h2>
+<ul><li> <!--c1--> <!--c2--> List item <!--c3--> <!--c4--> </li></ul>
+<table>
+<tbody><tr><th> <!--c1--> <!--c2--> Table Heading <!--c3--> <!--c4--> </th><th></th></tr>
+<tr><td> <!--c1--> <!--c2--> Table Cell <!--c3--> <!--c4--> </td><th></th></tr>
+</tbody></table>
+!! end
+
+!! test
+Do not trim whitespace in links and quotes
+!! options
+parsoid={
+ "modes": ["wt2html"],
+ "preserveIEW": true
+}
+!! wikitext
+foo '' <!--c1--> italic <!--c2--> '' and ''' <!--c3--> bold <!--c4--> '''
+[[Foo| some text ]]
+!! html/php+tidy
+<p>foo <i> italic </i> and <b> bold </b>
+<a href="/wiki/Foo" title="Foo"> some text </a>
+</p>
+!! html/parsoid
+<p>foo <i> <!--c1--> italic <!--c2--> </i> and <b> <!--c3--> bold <!--c4--> </b>
+<a rel="mw:WikiLink" href="./Foo" title="Foo"> some text </a></p>
+!! end
+
+!! test
+Remove p tags surrounding a single element in a figcaption
+!! options
+parsoid=html2wt
+!! wikitext
+[[File:Foobar.jpg|right|200x200px|Caption]]
+!! html/parsoid
+<figure class="mw-halign-right" typeof="mw:Image"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/200px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="23" width="200"/></a><figcaption><p>Caption</p></figcaption></figure>
+!! end
+
+!! test
+Selser preserves lack of newline before list and allows newline after the list
+!! options
+parsoid={
+ "modes": ["selser"],
+ "scrubWikitext": true,
+ "changes": [
+ [ "ul", "after", "<p>footer</p>" ]
+ ]
+}
+!! wikitext
+header
+*foo
+*bar
+!! wikitext/edited
+header
+*foo
+*bar
+
+footer
+!! end
+
+
+!! test
+Selser does not introduce newlines between unedited paragraph preceding the list
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [
+ [ "table tbody tr td p:last-child", "empty" ]
+ ]
+}
+!! wikitext
+{|
+|
+header
+*foo
+*bar
+footer
+|}
+!! wikitext/edited
+{|
+|
+header
+*foo
+*bar
+
+|}
+!! end
+
+!! test
+Selser does not introduce newlines between unedited paragraph following the list
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [
+ [ "table tbody tr td p:first-child", "empty" ]
+ ]
+}
+!! wikitext
+{|
+|
+header
+*foo
+*bar
+footer
+|}
+!! wikitext/edited
+{|
+|
+
+*foo
+*bar
+footer
+|}
+!! end
+
+!! test
+Remove a list item but do not insert newline above list
+!! options
+parsoid={
+ "modes": ["selser"],
+ "changes": [
+ [ "ul li:last-child", "remove" ]
+ ]
+}
+!! wikitext
+header
+*foo
+*bar
+footer
+!! wikitext/edited
+header
+*foo
+footer
+!! end