/** * @param ResourceLoaderContext $context * @return array */ public function getStyles(ResourceLoaderContext $context) { global $wgUser; if (!$this->getConfig()->get('AllowUserCssPrefs')) { return array(); } $options = $wgUser->getOptions(); // Build CSS rules $rules = array(); // Underline: 2 = browser default, 1 = always, 0 = never if ($options['underline'] < 2) { $rules[] = "a { text-decoration: " . ($options['underline'] ? 'underline' : 'none') . "; }"; } else { # The scripts of these languages are very hard to read with underlines $rules[] = 'a:lang(ar), a:lang(kk-arab), a:lang(mzn), ' . 'a:lang(ps), a:lang(ur) { text-decoration: none; }'; } if ($options['editfont'] !== 'default') { // Double-check that $options['editfont'] consists of safe characters only if (preg_match('/^[a-zA-Z0-9_, -]+$/', $options['editfont'])) { $rules[] = "textarea { font-family: {$options['editfont']}; }\n"; } } $style = implode("\n", $rules); if ($this->getFlip($context)) { $style = CSSJanus::transform($style, true, false); } else { $style = CSSJanus::nullTransform($style); } return array('all' => $style); }
/** * Reads a style file. * * This method can be used as a callback for array_map() * * @param string $path File path of style file to read * @param bool $flip * * @return string CSS data in script file * @throws MWException If the file doesn't exist */ protected function readStyleFile($path, $flip) { $localPath = $this->getLocalPath($path); $remotePath = $this->getRemotePath($path); if (!file_exists($localPath)) { $msg = __METHOD__ . ": style file not found: \"{$localPath}\""; wfDebugLog('resourceloader', $msg); throw new MWException($msg); } if ($this->getStyleSheetLang($localPath) === 'less') { $style = $this->compileLessFile($localPath); $this->hasGeneratedStyles = true; } else { $style = file_get_contents($localPath); } if ($flip) { $style = CSSJanus::transform($style, true, false); } else { $style = CSSJanus::nullTransform($style); } $localDir = dirname($localPath); $remoteDir = dirname($remotePath); // Get and register local file references $this->localFileRefs = array_merge($this->localFileRefs, CSSMin::getLocalFileReferences($style, $localDir)); return CSSMin::remap($style, $localDir, $remoteDir, true); }
/** * @param ResourceLoaderContext $context * @return array */ public function getStyles(ResourceLoaderContext $context) { $styles = array(); foreach ($this->getPages($context) as $titleText => $options) { if ($options['type'] !== 'style') { continue; } $title = Title::newFromText($titleText); if (!$title || $title->isRedirect()) { continue; } $media = isset($options['media']) ? $options['media'] : 'all'; $style = $this->getContent($title); if (strval($style) === '') { continue; } if ($this->getFlip($context)) { $style = CSSJanus::transform($style, true, false); } else { $style = CSSJanus::nullTransform($style); } $style = CSSMin::remap($style, false, $this->getConfig()->get('ScriptPath'), true); if (!isset($styles[$media])) { $styles[$media] = array(); } $style = ResourceLoader::makeComment($titleText) . $style; $styles[$media][] = $style; } return $styles; }
/** * Build a set of "<link>" elements for the stylesheets specified in the $this->styles array. * These will be applied to various media & IE conditionals. * * @return string */ public function buildCssLinks() { global $wgContLang; $this->getSkin()->setupSkinUserCss($this); // Add ResourceLoader styles // Split the styles into these groups $styles = array('other' => array(), 'user' => array(), 'site' => array(), 'private' => array(), 'noscript' => array()); $links = array(); $otherTags = ''; // Tags to append after the normal <link> tags $resourceLoader = $this->getResourceLoader(); $moduleStyles = $this->getModuleStyles(); // Per-site custom styles $moduleStyles[] = 'site'; $moduleStyles[] = 'noscript'; $moduleStyles[] = 'user.groups'; // Per-user custom styles if ($this->getConfig()->get('AllowUserCss') && $this->getTitle()->isCssSubpage() && $this->userCanPreview()) { // We're on a preview of a CSS subpage // Exclude this page from the user module in case it's in there (bug 26283) $link = $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_STYLES, false, array('excludepage' => $this->getTitle()->getPrefixedDBkey())); $otherTags .= $link['html']; // Load the previewed CSS // If needed, Janus it first. This is user-supplied CSS, so it's // assumed to be right for the content language directionality. $previewedCSS = $this->getRequest()->getText('wpTextbox1'); if ($this->getLanguage()->getDir() !== $wgContLang->getDir()) { $previewedCSS = CSSJanus::transform($previewedCSS, true, false); } else { $previewedCSS = CSSJanus::nullTransform($previewedCSS); } $otherTags .= Html::inlineStyle($previewedCSS) . "\n"; } else { // Load the user styles normally $moduleStyles[] = 'user'; } // Per-user preference styles $moduleStyles[] = 'user.cssprefs'; foreach ($moduleStyles as $name) { $module = $resourceLoader->getModule($name); if (!$module) { continue; } $group = $module->getGroup(); // Modules in groups different than the ones listed on top (see $styles assignment) // will be placed in the "other" group $styles[isset($styles[$group]) ? $group : 'other'][] = $name; } // We want site, private and user styles to override dynamically added // styles from modules, but we want dynamically added styles to override // statically added styles from other modules. So the order has to be // other, dynamic, site, private, user. Add statically added styles for // other modules $links[] = $this->makeResourceLoaderLink($styles['other'], ResourceLoaderModule::TYPE_STYLES); // Add normal styles added through addStyle()/addInlineStyle() here $links[] = implode("\n", $this->buildCssLinksArray()) . $this->mInlineStyles; // Add marker tag to mark the place where the client-side loader should inject dynamic styles // We use a <meta> tag with a made-up name for this because that's valid HTML $links[] = Html::element('meta', array('name' => 'ResourceLoaderDynamicStyles', 'content' => '')) . "\n"; // Add site, private and user styles // 'private' at present only contains user.options, so put that before 'user' // Any future private modules will likely have a similar user-specific character foreach (array('site', 'noscript', 'private', 'user') as $group) { $links[] = $this->makeResourceLoaderLink($styles[$group], ResourceLoaderModule::TYPE_STYLES); } // Add stuff in $otherTags (previewed user CSS if applicable) return self::getHtmlFromLoaderLinks($links) . $otherTags; }