* @var array List of paths to JavaScript files to always include
* @par Usage:
* @code
- * array( [file-path], [file-path], ... )
+ * [ [file-path], [file-path], ... ]
* @endcode
*/
protected $scripts = [];
* @var array List of JavaScript files to include when using a specific language
* @par Usage:
* @code
- * array( [language-code] => array( [file-path], [file-path], ... ), ... )
+ * [ [language-code] => [ [file-path], [file-path], ... ], ... ]
* @endcode
*/
protected $languageScripts = [];
* @var array List of JavaScript files to include when using a specific skin
* @par Usage:
* @code
- * array( [skin-name] => array( [file-path], [file-path], ... ), ... )
+ * [ [skin-name] => [ [file-path], [file-path], ... ], ... ]
* @endcode
*/
protected $skinScripts = [];
* @var array List of paths to JavaScript files to include in debug mode
* @par Usage:
* @code
- * array( [skin-name] => array( [file-path], [file-path], ... ), ... )
+ * [ [skin-name] => [ [file-path], [file-path], ... ], ... ]
* @endcode
*/
protected $debugScripts = [];
* @var array List of paths to CSS files to always include
* @par Usage:
* @code
- * array( [file-path], [file-path], ... )
+ * [ [file-path], [file-path], ... ]
* @endcode
*/
protected $styles = [];
* @var array List of paths to CSS files to include when using specific skins
* @par Usage:
* @code
- * array( [file-path], [file-path], ... )
+ * [ [file-path], [file-path], ... ]
* @endcode
*/
protected $skinStyles = [];
* @var array List of modules this module depends on
* @par Usage:
* @code
- * array( [file-path], [file-path], ... )
+ * [ [file-path], [file-path], ... ]
* @endcode
*/
protected $dependencies = [];
* @var array List of message keys used by this module
* @par Usage:
* @code
- * array( [message-key], [message-key], ... )
+ * [ [message-key], [message-key], ... ]
* @endcode
*/
protected $messages = [];
/** @var string Name of group to load this module in */
protected $group;
- /** @var string Position on the page to load this module at */
- protected $position = 'bottom';
-
/** @var bool Link to raw files in debug mode */
protected $debugRaw = true;
protected $targets = [ 'desktop' ];
+ /** @var bool Whether CSSJanus flipping should be skipped for this module */
+ protected $noflip = false;
+
/**
* @var bool Whether getStyleURLsForDebug should return raw file paths,
* or return load.php urls
* @var array Place where readStyleFile() tracks file dependencies
* @par Usage:
* @code
- * array( [file-path], [file-path], ... )
+ * [ [file-path], [file-path], ... ]
* @endcode
*/
protected $localFileRefs = [];
* @throws InvalidArgumentException
* @par Construction options:
* @code
- * array(
+ * [
* // Base path to prepend to all local paths in $options. Defaults to $IP
* 'localBasePath' => [base path],
* // Base path to prepend to all remote paths in $options. Defaults to $wgResourceBasePath
* // Scripts to always include
* 'scripts' => [file path string or array of file path strings],
* // Scripts to include in specific language contexts
- * 'languageScripts' => array(
+ * 'languageScripts' => [
* [language code] => [file path string or array of file path strings],
- * ),
+ * ],
* // Scripts to include in specific skin contexts
- * 'skinScripts' => array(
+ * 'skinScripts' => [
* [skin name] => [file path string or array of file path strings],
- * ),
+ * ],
* // Scripts to include in debug contexts
* 'debugScripts' => [file path string or array of file path strings],
* // Modules which must be loaded before this module
* 'dependencies' => [module name string or array of module name strings],
- * 'templates' => array(
+ * 'templates' => [
* [template alias with file.ext] => [file path to a template file],
- * ),
+ * ],
* // Styles to always load
* 'styles' => [file path string or array of file path strings],
* // Styles to include in specific skin contexts
- * 'skinStyles' => array(
+ * 'skinStyles' => [
* [skin name] => [file path string or array of file path strings],
- * ),
+ * ],
* // Messages to always load
* 'messages' => [array of message key strings],
* // Group which this module should be loaded together with
* 'group' => [group name string],
- * // Position on the page to load this module at
- * 'position' => ['bottom' (default) or 'top']
* // Function that, if it returns true, makes the loader skip this module.
* // The file must contain valid JavaScript for execution in a private function.
* // The file must not contain the "function () {" and "}" wrapper though.
* 'skipFunction' => [file path]
- * )
+ * ]
* @endcode
*/
public function __construct(
$this->{$member}[$key] = (array)$value;
}
break;
+ case 'deprecated':
+ $this->deprecated = $option;
+ break;
// Lists of strings
case 'dependencies':
case 'messages':
$this->{$member} = $option;
break;
// Single strings
- case 'position':
case 'group':
case 'skipFunction':
$this->{$member} = (string)$option;
// Single booleans
case 'debugRaw':
case 'raw':
+ case 'noflip':
$this->{$member} = (bool)$option;
break;
}
*/
public function getScript( ResourceLoaderContext $context ) {
$files = $this->getScriptFiles( $context );
- return $this->readScriptFiles( $files );
+ return $this->getDeprecationInformation() . $this->readScriptFiles( $files );
}
/**
return $this->group;
}
- /**
- * @return string
- */
- public function getPosition() {
- return $this->position;
- }
-
/**
* Gets list of names of modules this module depends on.
* @param ResourceLoaderContext|null $context
if ( !file_exists( $localPath ) ) {
throw new MWException( __METHOD__ . ": skip function file not found: \"$localPath\"" );
}
- $contents = file_get_contents( $localPath );
+ $contents = $this->stripBom( file_get_contents( $localPath ) );
if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
$contents = $this->validateScriptFile( $localPath, $contents );
}
// - dependencies (provided via startup module)
// - targets
// - group (provided via startup module)
- // - position (only used by OutputPage)
'scripts',
'debugScripts',
'styles',
if ( !file_exists( $localPath ) ) {
throw new MWException( __METHOD__ . ": script file not found: \"$localPath\"" );
}
- $contents = file_get_contents( $localPath );
+ $contents = $this->stripBom( file_get_contents( $localPath ) );
if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
// Static files don't really need to be checked as often; unlike
// on-wiki module they shouldn't change unexpectedly without
$style = $this->compileLessFile( $localPath, $context );
$this->hasGeneratedStyles = true;
} else {
- $style = file_get_contents( $localPath );
+ $style = $this->stripBom( file_get_contents( $localPath ) );
}
if ( $flip ) {
* @return bool
*/
public function getFlip( $context ) {
- return $context->getDirection() === 'rtl';
+ return $context->getDirection() === 'rtl' && !$this->noflip;
}
/**
return $this->targets;
}
+ /**
+ * Get the module's load type.
+ *
+ * @since 1.28
+ * @return string
+ */
+ public function getType() {
+ $canBeStylesOnly = !(
+ // All options except 'styles', 'skinStyles' and 'debugRaw'
+ $this->scripts
+ || $this->debugScripts
+ || $this->templates
+ || $this->languageScripts
+ || $this->skinScripts
+ || $this->dependencies
+ || $this->messages
+ || $this->skipFunction
+ || $this->raw
+ );
+ return $canBeStylesOnly ? self::LOAD_STYLES : self::LOAD_GENERAL;
+ }
+
/**
* Compile a LESS file into CSS.
*
$localPath = $this->getLocalPath( $templatePath );
if ( file_exists( $localPath ) ) {
$content = file_get_contents( $localPath );
- $templates[$alias] = $content;
+ $templates[$alias] = $this->stripBom( $content );
} else {
$msg = __METHOD__ . ": template file not found: \"$localPath\"";
wfDebugLog( 'resourceloader', $msg );
}
return $templates;
}
+
+ /**
+ * Takes an input string and removes the UTF-8 BOM character if present
+ *
+ * We need to remove these after reading a file, because we concatenate our files and
+ * the BOM character is not valid in the middle of a string.
+ * We already assume UTF-8 everywhere, so this should be safe.
+ *
+ * @return string input minus the intial BOM char
+ */
+ protected function stripBom( $input ) {
+ if ( substr_compare( "\xef\xbb\xbf", $input, 0, 3 ) === 0 ) {
+ return substr( $input, 3 );
+ }
+ return $input;
+ }
}