The UtfNormal\Utils class from the utfnormal library should be used instead.
* The deprecated UTF8_ and UNICODE_ constants were removed. The class constants
from the UtfNormal\Constants class from the utfnormal library should be used
+* (T140807) The wgResourceLoaderLESSImportPaths configuration option was removed
+ from ResourceLoader. Instead, use `@import` statements in LESS to import
+ files directly from nearby directories within the same project.
=== Deprecations in 1.32 ===
* Use of a StartProfiler.php file is deprecated in favour of placing
with the 'unwatch' action parameter instead.
* IcuCollation::getICUVersion() is deprecated, as you can just use the PHP
constant INTL_ICU_VERSION directly in all versions that MediaWiki supports.
+* Parser::fetchFile() is deprecated. Use ::fetchFileAndTitle() instead.
=== Other changes in 1.32 ===
* Soft hyphens (U+00AD) are now automatically removed from titles; these
'deviceWidthTablet' => '720px',
];
-/**
- * Default import paths for LESS modules. LESS files referenced in @import
- * statements will be looked up here first, and relative to the importing file
- * second. To avoid collisions, it's important for the LESS files in these
- * directories to have a common, predictable file name prefix.
- *
- * Extensions need not (and should not) register paths in
- * $wgResourceLoaderLESSImportPaths. The import path includes the path of the
- * currently compiling LESS file, which allows each extension to freely import
- * files from its own tree.
- *
- * @since 1.22
- */
-$wgResourceLoaderLESSImportPaths = [
- "$IP/resources/src/mediawiki.less/",
-];
-
/**
* Whether ResourceLoader should attempt to persist modules in localStorage on
* browsers that support the Web Storage API.
* @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];
}
* @return Less_Parser
*/
public function getLessCompiler( $vars = [] ) {
+ global $IP;
// When called from the installer, it is possible that a required PHP extension
// is missing (at least for now; see T49564). If this is the case, throw an
// exception (caught by the installer) to prevent a fatal error later on.
$parser = new Less_Parser;
$parser->ModifyVars( $vars );
- $parser->SetImportDirs(
- array_fill_keys( $this->config->get( 'ResourceLoaderLESSImportPaths' ), '' )
- );
+ $parser->SetImportDirs( [
+ "$IP/resources/src/mediawiki.less/" => '',
+ ] );
$parser->SetOption( 'relativeUrls', false );
return $parser;
$out = $this->getOutput();
$out->addModuleStyles( 'mediawiki.special' );
- $this->addHelpLink( 'Help:Password policies' );
+ // TODO: Have specific user documentation page for this feature
+ $this->addHelpLink( 'Manual:$wgPasswordPolicy' );
$out->addHTML(
Xml::openElement( 'table', [ 'class' => 'wikitable mw-passwordpolicies-table' ] ) .
"unregistered-user-config": "For security reasons JavaScript, CSS and JSON user subpages cannot be loaded for unregistered users.",
"passwordpolicies": "Password policies",
"passwordpolicies-summary": "This is a list of the effective password policies for the user groups defined in this wiki.",
- "passwordpolicies-helppage": "Manual:$wgPasswordPolicy",
"passwordpolicies-group": "Group",
"passwordpolicies-policies": "Policies",
"passwordpolicies-policy-display": "<span class=\"passwordpolicies-policy\">$1 <code>($2)</code></span>",
"unregistered-user-config": "Shown when viewing a user JS, CSS or JSON subpage with ?action=raw&ctype=<mime type> where there is no such user. It is shown as a paragraph after a header saying 'Forbidden'.",
"passwordpolicies": "The name of the special page [[Special:PasswordPolicies]].",
"passwordpolicies-summary": "The description used on [[Special:PasswordPolicies]].\n\nRefers to {{msg-mw|Passwordpolicies-helppage}}.",
- "passwordpolicies-helppage": "The link used on [[Special:PasswordPolicies]].",
"passwordpolicies-group": "The title of the column in the table, about user groups (like you are in the ''translator'' group).\n\n{{Identical|Group}}\n{{Related|Passwordpolicies}}",
"passwordpolicies-policies": "The title of the column in the table, about password policies.\n{{Related|Passwordpolicies}}",
"passwordpolicies-policy-display": "{{optional}}\nParameters:\n* $1 - the text from the \"passwordpolicies-policy-...\" messages, i.e. {{msg-mw|passwordpolicies-policy-minimalpasswordlength}}\n* $2 - the name of this password policy",
@ooui-spacing-medium: 12 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.8571429em`≈`12px`
@ooui-spacing-large: 16 / @ooui-font-size-browser / @ooui-font-size-base; // equals `1.1428571em`≈`16px`
+@ooui-padding-horizontal: 12 / @ooui-font-size-browser / @ooui-font-size-base;
+@ooui-padding-vertical: 4 / @ooui-font-size-browser / @ooui-font-size-base; // equals `0.285714em`≈`4px`
.mw-htmlform-ooui-wrapper.oo-ui-panelLayout-padded {
padding: @ooui-spacing-medium @ooui-spacing-large @ooui-spacing-large;
}
.mw-htmlform-matrix {
- border-spacing: 0;
+ border-spacing: 0 2px;
td {
- padding: 0.35em 0.7em;
+ padding: @ooui-padding-vertical @ooui-padding-horizontal;
+ text-align: center;
.transition( background-color 250ms );
+
+ &:first-child {
+ text-align: left;
+ }
}
tbody tr:nth-child( even ) td {
tbody tr:first-child td {
background-color: #fff;
+ padding-bottom: 0;
}
td.first {
// Common Less mixin library for MediaWiki
//
-// By default the folder containing this file is included in $wgResourceLoaderLESSImportPaths,
+// By default the folder containing this file is included in the LESS import paths,
// which makes this file importable by all less files via `@import 'mediawiki.mixins';`.
//
// The mixins included below are considered a public interface for MediaWiki extensions.
FOO
!!endarticle
+!! article
+Template:redirect to foo
+!! text
+#REDIRECT [[Template:Foo]]
+!! endarticle
+
!! article
Template:Blank
!! text
</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
{
"name": "FooBar",
- "manifest_version": 1
+ "attributes": {
+ "FooBar": {
+ "Attr": [ "test" ]
+ },
+ "NotLoaded": {
+ "Attr": [ "test2" ]
+ }
+ },
+ "manifest_version": 2
}
$registry->loadFromQueue();
}
+ public function testLoadFromQueue() {
+ $registry = new ExtensionRegistry();
+ $registry->queue( "{$this->dataDir}/good.json" );
+ $registry->loadFromQueue();
+ $this->assertArrayHasKey( 'FooBar', $registry->getAllThings() );
+ $this->assertTrue( $registry->isLoaded( 'FooBar' ) );
+ $this->assertSame( [ 'test' ], $registry->getAttribute( 'FooBarAttr' ) );
+ $this->assertSame( [], $registry->getAttribute( 'NotLoadedAttr' ) );
+ }
+
+ /**
+ * @expectedException PHPUnit_Framework_Error
+ */
+ public function testReadFromQueue_nonexistent() {
+ $registry = new ExtensionRegistry();
+ $registry->readFromQueue( [
+ __DIR__ . '/doesnotexist.json' => 1
+ ] );
+ }
+
/**
* @dataProvider provideExportExtractedDataGlobals
*/
parent::setUp();
$this->setMwGlobals( [
- 'wgResourceLoaderLESSImportPaths' => [],
'wgResourceLoaderLESSVars' => [
'foo' => '2px',
'Foo' => '#eeeeee',
$this->assertEquals( $expected, $response, $message ?: 'Response' );
}
+ /**
+ * @covers ResourceLoader::makeModuleResponse
+ */
+ public function testMakeModuleResponseEmpty() {
+ $rl = new EmptyResourceLoader();
+ $context = $this->getResourceLoaderContext(
+ [ 'modules' => '', 'only' => 'scripts' ],
+ $rl
+ );
+
+ $response = $rl->makeModuleResponse( $context, [] );
+ $this->assertSame( [], $rl->getErrors(), 'Errors' );
+ $this->assertRegExp( '/^\/\*.+no modules were requested.+\*\/$/ms', $response );
+ }
+
/**
* Verify that when building module content in a load.php response,
* an exception from one module will not break script output from
$this->assertCount( 2, $errors );
$this->assertRegExp( '/Ferry not found/', $errors[0] );
- $this->assertRegExp( '/Problem.+\n\s*"ferry":\s*"error"/m', $errors[1] );
+ $this->assertRegExp( '/Problem.+"ferry":\s*"error"/ms', $errors[1] );
$this->assertEquals(
'.foo{}.bar{}',
$response