*/
use MediaWiki\Logger\LoggerFactory;
+use WrappedString\WrappedString;
/**
* This class should be covered by a general architecture document which does
$modules = (array)$modules;
$links = array(
- 'html' => '',
+ // List of html strings
+ 'html' => array(),
+ // Associative array of module names and their states
'states' => array(),
);
// Recursively call us for every item
foreach ( $modules as $name ) {
$link = $this->makeResourceLoaderLink( $name, $only, $useESI );
- $links['html'] .= $link['html'];
+ $links['html'] = array_merge( $links['html'], $link['html'] );
$links['states'] += $link['states'];
}
return $links;
// properly use them as dependencies (bug 30914)
if ( $group === 'private' ) {
if ( $only == ResourceLoaderModule::TYPE_STYLES ) {
- $links['html'] .= Html::inlineStyle(
+ $links['html'][] = Html::inlineStyle(
$resourceLoader->makeModuleResponse( $context, $grpModules )
);
} else {
- $links['html'] .= ResourceLoader::makeInlineScript(
+ $links['html'][] = ResourceLoader::makeInlineScript(
$resourceLoader->makeModuleResponse( $context, $grpModules )
);
}
- $links['html'] .= "\n";
continue;
}
}
if ( $group == 'noscript' ) {
- $links['html'] .= Html::rawElement( 'noscript', array(), $link ) . "\n";
+ $links['html'][] = Html::rawElement( 'noscript', array(), $link );
} else {
- $links['html'] .= $link . "\n";
+ $links['html'][] = $link;
}
}
}
* @return string HTML
*/
protected static function getHtmlFromLoaderLinks( array $links ) {
- $html = '';
+ $html = array();
$states = array();
foreach ( $links as $link ) {
if ( !is_array( $link ) ) {
- $html .= $link;
+ $html[] = $link;
} else {
- $html .= $link['html'];
+ $html = array_merge( $html, $link['html'] );
$states += $link['states'];
}
}
+ // Filter out empty values
+ $html = array_filter( $html, 'strlen' );
if ( count( $states ) ) {
- $html = ResourceLoader::makeInlineScript(
+ array_unshift( $html, ResourceLoader::makeInlineScript(
ResourceLoader::makeLoaderStateScript( $states )
- ) . "\n" . $html;
+ ) );
}
- return $html;
+ return WrappedString::join( "\n", $html );
}
/**
}
// Legacy Scripts
- $links[] = "\n" . $this->mScripts;
+ $links[] = $this->mScripts;
// Add user JS if enabled
// This must use TYPE_COMBINED instead of only=scripts so that its request is handled by
'noscript' => array()
);
$links = array();
- $otherTags = ''; // Tags to append after the normal <link> tags
+ $otherTags = array(); // Tags to append after the normal <link> tags
$resourceLoader = $this->getResourceLoader();
$moduleStyles = $this->getModuleStyles( true, 'top' );
$link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,
array( 'excludepage' => $this->getTitle()->getPrefixedDBkey() )
);
- $otherTags .= $link['html'];
+ $otherTags = array_merge( $otherTags, $link['html'] );
// Load the previewed CSS
// If needed, Janus it first. This is user-supplied CSS, so it's
if ( $this->getLanguage()->getDir() !== $wgContLang->getDir() ) {
$previewedCSS = CSSJanus::transform( $previewedCSS, true, false );
}
- $otherTags .= Html::inlineStyle( $previewedCSS ) . "\n";
+ $otherTags[] = Html::inlineStyle( $previewedCSS ) . "\n";
} else {
// Load the user styles normally
$moduleStyles[] = 'user';
$links[] = Html::element(
'meta',
array( 'name' => 'ResourceLoaderDynamicStyles', 'content' => '' )
- ) . "\n";
+ );
// Add site-specific and user-specific styles
// 'private' at present only contains user.options, so put that before 'user'
}
// Add stuff in $otherTags (previewed user CSS if applicable)
- return self::getHtmlFromLoaderLinks( $links ) . $otherTags;
+ return self::getHtmlFromLoaderLinks( $links ) . implode( '', $otherTags );
}
/**
. 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?'
. 'debug=false\u0026amp;lang=en\u0026amp;modules=test.foo\u0026amp;only'
. '=scripts\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
- . "\n} );</script>\n"
+ . "\n} );</script>"
),
array(
// Don't condition wrap raw modules (like the startup module)
array( 'test.raw', ResourceLoaderModule::TYPE_SCRIPTS ),
- '<script src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.raw&only=scripts&skin=fallback&*"></script>
-'
+ '<script src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.raw&only=scripts&skin=fallback&*"></script>'
),
// Load module styles only
// This also tests the order the modules are put into the url
array(
array( array( 'test.baz', 'test.foo', 'test.bar' ), ResourceLoaderModule::TYPE_STYLES ),
- '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.bar%2Cbaz%2Cfoo&only=styles&skin=fallback&*">
-'
+ '<link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.bar%2Cbaz%2Cfoo&only=styles&skin=fallback&*">'
),
// Load private module (only=scripts)
array(
array( 'test.quux', ResourceLoaderModule::TYPE_SCRIPTS ),
"<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
. "mw.test.baz({token:123});mw.loader.state({\"test.quux\":\"ready\"});\n"
- . "\n} );</script>\n"
+ . "\n} );</script>"
),
// Load private module (combined)
array(
"<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
. "mw.loader.implement(\"test.quux\",function($,jQuery){"
. "mw.test.baz({token:123});},{\"css\":[\".mw-icon{transition:none}\\n"
- . "\"]});\n\n} );</script>\n"
+ . "\"]});\n\n} );</script>"
),
// Load module script with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
- '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=scripts&skin=fallback&*" /></script>
-'
+ '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=scripts&skin=fallback&*" /></script>'
),
// Load module styles with ESI
array(
array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
- '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=styles&skin=fallback&*" /></style>
-',
+ '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.foo&only=styles&skin=fallback&*" /></style>',
),
// Load no modules
array(
// noscript group
array(
array( 'test.noscript', ResourceLoaderModule::TYPE_STYLES ),
- '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.noscript&only=styles&skin=fallback&*"></noscript>
-'
+ '<noscript><link rel=stylesheet href="http://127.0.0.1:8080/w/load.php?debug=false&lang=en&modules=test.noscript&only=styles&skin=fallback&*"></noscript>'
),
// Load two modules in separate groups
array(
. "\n} );</script>\n"
. "<script>var RLQ = RLQ || []; RLQ.push( function () {\n"
. 'document.write("\u003Cscript src=\"http://127.0.0.1:8080/w/load.php?debug=false\u0026amp;lang=en\u0026amp;modules=test.group.foo\u0026amp;skin=fallback\u0026amp;*\"\u003E\u003C/script\u003E");'
- . "\n} );</script>\n"
+ . "\n} );</script>"
),
);
}
) );
$links = $method->invokeArgs( $out, $args );
// Strip comments to avoid variation due to wgDBname in WikiID and cache key
- $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', $links['html'] );
+ $actualHtml = preg_replace( '#/\*[^*]+\*/#', '', implode( "\n", $links['html'] ) );
$this->assertEquals( $expectedHtml, $actualHtml );
}
}