/** * Filters an asset after it has been loaded. * * @param \Assetic\Asset\AssetInterface $asset * @return void */ public function filterLoad(AssetInterface $asset) { $max_nesting_level = ini_get('xdebug.max_nesting_level'); $memory_limit = ini_get('memory_limit'); if ($max_nesting_level && $max_nesting_level < 200) { ini_set('xdebug.max_nesting_level', 200); } if ($memory_limit && $memory_limit < 256) { ini_set('memory_limit', '256M'); } $root = $asset->getSourceRoot(); $path = $asset->getSourcePath(); $dirs = array(); $lc = new \Less_Parser(array('compress' => true)); if ($root && $path) { $dirs[] = dirname($root . '/' . $path); } foreach ($this->loadPaths as $loadPath) { $dirs[] = $loadPath; } $lc->SetImportDirs($dirs); $url = parse_url($this->getRequest()->getUriForPath('')); $absolutePath = str_replace(public_path(), '', $root); if (isset($url['path'])) { $absolutePath = $url['path'] . $absolutePath; } $lc->parseFile($root . '/' . $path, $absolutePath); $asset->setContent($lc->getCss()); }
public function Compile($less_files, $out_name, $modify_vars = [], $bootstrap_less = "mixins", $mediawiki_less = "mixins") { $lessphp = new \Less_Parser($this->cache_dir); switch ($bootstrap_less) { case "mixins": $lessphp->parseFile($this->bootstrap_dir . "/variables.less", ""); $lessphp->parseFile(__DIR__ . "/custom_variables.less", ""); $lessphp->parseFile($this->bootstrap_mixin, $this->bootstrap_mixin_url); break; case "full": $lessphp->SetImportDirs([$this->bootstrap_dir]); $lessphp->parseFile(__DIR__ . "/bootstrap.less", ""); break; case "off": break; } switch ($mediawiki_less) { case "mixins": $lessphp->parseFile($this->mediawiki_mixin, $this->mediawiki_mixin_url); break; case "off": break; } foreach ($less_files as $less => $url) { $lessphp->parseFile($less, $url); } if ($modify_vars) { $lessphp->ModifyVars($modify_vars); } $css = $lessphp->getCss(); file_put_contents($out_name, $css); }
public function compileFile($fname, $outFname = null) { if (!is_readable($fname)) { throw new Exception('load error: failed to find ' . $fname); } $pi = pathinfo($fname); $oldImport = $this->importDir; $this->importDir = (array) $this->importDir; $this->importDir[] = realpath($pi['dirname']) . '/'; $this->allParsedFiles = array(); $this->addParsedFile($fname); $parser = new Less_Parser(array('sourceMap' => $this->sourceMap)); $parser->SetImportDirs($this->getImportDirs()); if (count($this->registeredVars)) { $parser->ModifyVars($this->registeredVars); } foreach ($this->libFunctions as $name => $func) { $parser->registerFunction($name, $func); } $parser->parseFile($fname); $out = $parser->getCss(); $parsed = Less_Parser::AllParsedFiles(); foreach ($parsed as $file) { $this->addParsedFile($file); } $this->importDir = $oldImport; if ($outFname !== null) { return file_put_contents($outFname, $out); } return $out; }
public static function Cache(&$less_files, $parser_options = array()) { //prepare the processor if (!class_exists('Less_Parser')) { include_once 'Less.php'; } $parser = new Less_Parser($parser_options); $parser->SetCacheDir(self::$cache_dir); $parser->SetImportDirs(self::$import_dirs); // combine files try { foreach ($less_files as $file_path => $uri_or_less) { //treat as less markup if there are newline characters if (strpos($uri_or_less, "\n") !== false) { $parser->Parse($uri_or_less); continue; } $parser->ParseFile($file_path, $uri_or_less); } $compiled = $parser->getCss(); } catch (Exception $e) { self::$error = $e; return false; } $less_files = $parser->allParsedFiles(); return $compiled; }
public function compile($source, $pathname) { $less = new \Less_Parser(); $less->SetImportDirs(array(dirname($pathname) => './')); $less->parse($source); return $less->getCss(); }
/** * @param string $themeName * @param string $lessFile * @return string */ public function compileFile($themeName, $lessFile) { $model = Model::instance(); $theme = $model->getTheme($themeName); $options = $theme->getOptionsAsArray(); $configModel = ConfigModel::instance(); $config = $configModel->getAllConfigValues($themeName); $less = "@import '{$lessFile}';"; $less .= $this->generateLessVariables($options, $config); $css = ''; try { require_once ipFile('Ip/Lib/less.php/Less.php'); $themeDir = ipFile('Theme/' . $themeName . '/assets/'); $ipContentDir = ipFile('Ip/Internal/Core/assets/ipContent/'); // creating new context to pass theme assets directory dynamically to a static callback function $context = $this; $callback = function ($parseFile) use($context, $themeDir) { return $context->overrideImportDirectory($themeDir, $parseFile); }; $parserOptions = array('import_callback' => $callback, 'cache_dir' => ipFile('file/tmp/less/'), 'relativeUrls' => false, 'sourceMap' => true); $parser = new \Less_Parser($parserOptions); $directories = array($themeDir => '', $ipContentDir => ''); $parser->SetImportDirs($directories); $parser->parse($less); $css = $parser->getCss(); $css = "/* Edit {$lessFile}, not this file. */" . "\n" . $css; } catch (\Exception $e) { ipLog()->error('Less compilation error: Theme - ' . $e->getMessage()); } return $css; }
function compile_botstrap_less_adm($theme, $input, $output = '', $compress = false) { global $cfg; $output = empty($output) ? $input : $output; $output = $cfg['themes_dir'] . '/admin/' . $theme . '/css/' . $output . '.css'; $input = $cfg['themes_dir'] . '/admin/' . $theme . '/less/' . $input . '.less'; if (file_exists($output) && file_exists($input)) { $filetimecss = filemtime($output); $filetimeless = filemtime($input); // cot_print('css', cot_date('datetime_full', $filetimecss), 'less', cot_date('datetime_full', $filetimeless), cot_date('datetime_full'), $filetimecss > $filetimeless); if ($filetimecss > $filetimeless) { return false; } else { unlink($output); // cot_print("deleted"); } } $options = array('relativeUrls' => false); if ($compress) { $options['compress'] = true; } $parser = new Less_Parser($options); $parser->SetImportDirs(array($cfg['themes_dir'] . '/admin/' . $theme . '/less' => $cfg['themes_dir'] . '/admin/' . $theme . '/less', $cfg['plugins_dir'] . "/bootstrap/bootstrap/less" => $cfg['plugins_dir'] . "/bootstrap/bootstrap/less")); $parser->parseFile($input); $css = $parser->getCss(); if (!file_exists($cfg['themes_dir'] . '/admin/' . $theme . '/css')) { mkdir($cfg['themes_dir'] . '/admin/' . $theme . '/css'); } file_put_contents($output, $css); return true; }
public static function compile($source, $path, $todir, $importdirs) { $parser = new Less_Parser(); $parser->SetImportDirs($importdirs); $parser->parse($source, CANVASLess::relativePath($todir, dirname($path)) . basename($path)); $output = $parser->getCss(); return $output; }
public static function compile($source, $importdirs) { $parser = new Less_Parser(); $parser->SetImportDirs($importdirs); $parser->parse($source); $output = $parser->getCss(); return $output; }
/** * {@inheritdoc} */ public function setImportPath($fullPath, $relPath = null) { $this->_initCompiler(); $relPath = $relPath ?: $this->_options->get('root_url'); if (!FS::isDir($fullPath)) { throw new Exception('Undefined import path: ' . $fullPath); } $importPaths = \Less_Parser::$options['import_dirs']; $importPaths[$fullPath] = $relPath; $this->_compiler->SetImportDirs($importPaths); }
/** * {@inheritdoc} */ public function compile($path, $relativePath) { $this->parsedFiles = array(); $parser = new \Less_Parser(array('compress' => true)); if (!empty($this->importDirs)) { $parser->SetImportDirs($this->importDirs); } $parser->parseFile($path); $parser->ModifyVars($this->variables); $css = $parser->getCss(); $this->parsedFiles = $parser->allParsedFiles(); return $css; }
public function register() { Event::listen('watcher:check', function ($options) { $timestamp = strtotime($options->timestamp); $reload = false; if (isset($options->less_process) && is_array($options->less_process) && $timestamp) { $lessCompiler = new \Less_Parser(); if (isset($options->less_importdirs) && is_array($options->less_importdirs)) { $importDirs = array(); foreach ($options->less_importdirs as $importdir) { $importdir = realpath(base_path($importdir)); if (is_dir($importdir)) { $importDirs[] = $importdir; foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($importdir)) as $x) { if (!$x->isDir() && $x->getCTime() > $timestamp) { $reload = true; } } } } $lessCompiler->SetImportDirs($importDirs); } foreach ($options->less_process as $source => $output) { $source = realpath(base_path($source)); $output = realpath(base_path($output)); if (!$output) { $output = base_path($output); } if (is_file($source)) { if ($reload) { touch($source); } if (filemtime($source) > $timestamp || $reload) { try { $lessCompiler->parseFile($source, '/'); $css = $lessCompiler->getCss(); if ($css) { file_put_contents($output, $css); } } catch (Exception $e) { } } } } } }); }
/** * @return Less_Parser */ protected function _initProcessor() { // lazy load if (!class_exists('Less_Parser')) { require_once dirname(__FILE__) . '/class.less.gpeasy.php'; } $options = array('compress' => true, 'strictUnits' => false, 'strictMath' => false, 'numPrecision' => 4, 'cache_method' => false); if ($this->_isDebug()) { $options['compress'] = false; } $less = new Less_Parser($options); // set paths $less->SetImportDirs(array($this->_tpl->lessFull => $this->_tpl->baseurl)); // add custom vars $less->ModifyVars(array()); return $less; }
/** * less compiler * @link https://github.com/oyejorge/less.php * * @param string $file * @return string */ protected function less($file) { if (!class_exists('\\Less_Parser')) { return Result::errorMissingPackage($this, 'Less_Parser', 'oyejorge/less.php'); } $lessCode = file_get_contents($file); $parser = new \Less_Parser(); $parser->SetOptions($this->compilerOptions); if (isset($this->compilerOptions['importDirs'])) { $importDirs = []; foreach ($this->compilerOptions['importDirs'] as $dir) { $importDirs[$dir] = $dir; } $parser->SetImportDirs($importDirs); } $parser->parse($lessCode); return $parser->getCss(); }
/** * @return Less_Parser */ protected function _initProcessor() { // lazy load if (!class_exists('Less_Parser')) { require_once dirname(__FILE__) . '/class.less.gpeasy.php'; } $options = array('compress' => 1, 'strictUnits' => 0, 'strictMath' => 0, 'relativeUrls' => 1, 'numPrecision' => 4, 'cache_method' => 0, 'sourceMap' => 0); if ($this->_isDebug()) { $options['compress'] = 0; $options['sourceMap'] = 1; $options['sourceMapRootpath'] = $this->_tpl->less; $options['sourceMapBasepath'] = $path = JPath::clean($this->_tpl->lessFull, '/'); } $less = new Less_Parser($options); // set paths $less->SetImportDirs(array($this->_tpl->lessFull => $this->_tpl->less)); // add custom vars $less->ModifyVars($this->_getCustomVars()); return $less; }
public function less_compile($observer) { $setting = Mage::helper('creative/data'); $less_theme_compile = Mage::getStoreConfig('creative_cfg/advanced/less_compile'); $preset_name = Mage::getStoreConfig('creative_cfg/general/color'); $device_responsive = Mage::getStoreConfig('creative_cfg/general/device_responsive'); if (!Mage::app()->getStore()->isAdmin() && $less_theme_compile) { if (!class_exists('Less_Parser')) { include_once Mage::getBaseDir('lib') . 'Less/Version.php'; include_once Mage::getBaseDir('lib') . 'Less/Parser.php'; } if (class_exists('Less_Parser') && $less_theme_compile) { $skin_base_dir = Mage::getDesign()->getSkinBaseDir(); $skin_base_url = Mage::getDesign()->getSkinUrl(); define('LESS_PATH', $skin_base_dir . '/less'); define('CSS__PATH', $skin_base_dir . '/css'); $import_dirs = array(LESS_PATH . '/path/' => $skin_base_url . '/less/path/', LESS_PATH . '/bootstrap/' => $skin_base_url . '/less/bootstrap/'); $options = array('compress' => true); if (file_exists(LESS_PATH . '/theme.less') && $less_theme_compile) { if ($preset_name) { $output_cssf = CSS__PATH . '/theme-' . $preset_name . '.css'; } else { $output_cssf = CSS__PATH . '/theme-default.css'; } $less = new Less_Parser($options); $less->SetImportDirs($import_dirs); $less->parseFile(LESS_PATH . '/theme.less', $skin_base_url . 'css/'); if (file_exists(LESS_PATH . '/theme-' . $preset_name . '.less')) { $less->parseFile(LESS_PATH . '/theme-' . $preset_name . '.less', $skin_base_url . 'css/'); } if ($device_responsive == 1) { $less->parseFile(LESS_PATH . '/path/yt-responsive.less', $skin_base_url . 'css/'); } else { $less->parseFile(LESS_PATH . '/path/yt-non-responsive.less', $skin_base_url . 'css/'); } $cache = $less->getCss(); file_put_contents($output_cssf, $cache); } } } }
/** * {@inheritdoc} */ public function filterLoad(AssetInterface $asset) { $parser = new \Less_Parser(array('compress' => 'compressed' == $this->formatter, 'relativeUrls' => false)); $importDirs = array_fill_keys((array) $this->loadPaths, '/'); $importDirs[dirname($asset->getSourceRoot() . '/' . $asset->getSourcePath())] = '/'; $webDir = $this->webDir; $importDirs[] = function ($path) use($webDir) { $file = $webDir . '/' . $path; foreach (array('', '.less', '.css') as $extension) { if (file_exists($file . $extension)) { return array($file . $extension, null); } } return null; }; $parser->SetImportDirs($importDirs); $content = $asset->getContent(); $parser->parse($content); $css = $parser->getCss(); $this->cache->set(md5($content), \Less_Parser::AllParsedFiles()); $asset->setContent($css); }
/** * Handle the processing of multiple less files into css * * @return mixed Compiled css string or false * */ static function ParseLess(&$less_files) { global $dataDir; $compiled = false; // don't use less if the memory limit is less than 64M $limit = @ini_get('memory_limit'); if ($limit) { $limit = \gp\tool::getByteValue($limit); //if less than 64M, disable less compiler if we can't increase if ($limit < 67108864 && @ini_set('memory_limit', '96M') === false) { if (\gp\tool::LoggedIn()) { msg('LESS compilation disabled. Please increase php\'s memory_limit'); } return false; //if less than 96M, try to increase } elseif ($limit < 100663296) { @ini_set('memory_limit', '96M'); } } //compiler options $options = array(); //prepare the compiler includeFile('thirdparty/less.php/Less.php'); $parser = new \Less_Parser($options); $import_dirs[$dataDir] = \gp\tool::GetDir('/'); $parser->SetImportDirs($import_dirs); $parser->cache_method = 'php'; $parser->SetCacheDir($dataDir . '/data/_cache'); // combine files try { foreach ($less_files as $less) { //treat as less markup if there are newline characters if (strpos($less, "\n") !== false) { $parser->Parse($less); continue; } // handle relative and absolute paths if (!empty($dataDir) && strpos($less, $dataDir) === false) { $relative = $less; $less = $dataDir . '/' . ltrim($less, '/'); } else { $relative = substr($less, strlen($dataDir)); } $parser->ParseFile($less, \gp\tool::GetDir(dirname($relative))); } $compiled = $parser->getCss(); } catch (Exception $e) { if (\gp\tool::LoggedIn()) { msg('LESS Compile Failed: ' . $e->getMessage()); } return false; } // significant difference in used memory 15,000,000 -> 6,000,000. Max still @ 15,000,000 if (function_exists('gc_collect_cycles')) { gc_collect_cycles(); } $less_files = $parser->allParsedFiles(); return $compiled; }
public function __invoke($fileName) { //Only include files once static $existingCssFiles = array(); if (in_array($fileName, $existingCssFiles)) { return; } $existingCssFiles[] = $fileName; //Preprocess .less files first $fileParts = explode(".", $fileName); $ext = array_pop($fileParts); if ($ext == "less") { if (getenv('APPLICATION_ENV') == 'development') { //Resolve asset $pluginManager = $this->getView()->getHelperPluginManager(); $sm = $pluginManager->getServiceLocator(); $assetManager = $sm->get('AssetManager\\Service\\AssetManager'); $resolver = $assetManager->getResolver(); $asset = $resolver->resolve($fileName); $config = $sm->get('Config'); $paths = $config['asset_manager']['resolver_configs']['prioritized_paths']; $themeDir = null; try { $param = new \ATPCore\Model\Parameter(); $param->loadByIdentifier('core-theme'); $themeDir = $param->value; } catch (\Exception $e) { } if (empty($themeDir)) { $themeDir = "Default"; } $paths[] = array("path" => realpath("themes/{$themeDir}/public"), "priority" => 5000); usort($paths, function ($a, $b) { return $b['priority'] - $a['priority']; }); $paths = \ATP\MapReduce::process($paths, function ($pathData) { return array($pathData['path'] => ''); }, function ($joined, $cur) { return array_merge($joined, $cur); }, array()); //Set original and compiled filenames $originalFile = $asset ? $asset->getSourceDirectory() . '/' . $asset->getSourcePath() : getcwd() . "/public" . $fileName; $compiledFile = substr($originalFile, 0, -4) . "css"; //Initialize less compiler $lessc = new \Less_Parser(); //Make the definitions file available to all less files $lessc->SetImportDirs($paths); //Compile the less code try { set_time_limit(60); $lessc->parseFile($originalFile); file_put_contents($compiledFile, $lessc->getCss()); } catch (\Exception $e) { echo "Less compilation error while compiling <b>{$fileName}</b>: <br/>" . $e->getMessage(); die; } } //Set new filename $fileName = substr($fileName, 0, -4) . "css"; } $func = $this->_function; $this->getView()->headLink()->{$func}($this->getView()->basePath() . $fileName); return $this->getView(); }
/** * @param \Less_Parser $oParser * @return \AssetsBundle\AssetFile\AssetFileFilter\LessphpAssetFileFilter */ public function setLessParser(\Less_Parser $oParser) { $oParser->SetImportDirs(array(getcwd() => getcwd())); $this->lessParser = $oParser; return $this; }
/** * Minify CSS * * @return string */ protected function minifyCss() { $output = ''; // Core variables and mixins $output .= '@import "variables.less";'; $output .= '@import "mixins.less";'; // Reset and dependencies $output .= $this->prepareCssForLess('normalize'); $output .= $this->prepareCssForLess('print'); $output .= $this->prepareCssForLess('glyphicons'); // Core CSS $output .= $this->prepareCssForLess('scaffolding'); $output .= $this->prepareCssForLess('type'); $output .= $this->prepareCssForLess('code'); $output .= $this->prepareCssForLess('grid'); $output .= $this->prepareCssForLess('tables'); $output .= $this->prepareCssForLess('forms'); $output .= $this->prepareCssForLess('buttons'); // Components $output .= $this->prepareCssForLess('component-animations'); $output .= $this->prepareCssForLess('dropdowns'); $output .= $this->prepareCssForLess('button-groups'); $output .= $this->prepareCssForLess('input-groups'); $output .= $this->prepareCssForLess('navs'); $output .= $this->prepareCssForLess('navbar'); $output .= $this->prepareCssForLess('breadcrumbs'); $output .= $this->prepareCssForLess('pagination'); $output .= $this->prepareCssForLess('pager'); $output .= $this->prepareCssForLess('labels'); $output .= $this->prepareCssForLess('badges'); $output .= $this->prepareCssForLess('jumbotron'); $output .= $this->prepareCssForLess('thumbnails'); $output .= $this->prepareCssForLess('alerts'); $output .= $this->prepareCssForLess('progress-bars'); $output .= $this->prepareCssForLess('media'); $output .= $this->prepareCssForLess('list-group'); $output .= $this->prepareCssForLess('panels'); $output .= $this->prepareCssForLess('responsive-embed'); $output .= $this->prepareCssForLess('wells'); $output .= $this->prepareCssForLess('close'); // Components w/ JavaScript $output .= $this->prepareCssForLess('modals'); $output .= $this->prepareCssForLess('tooltip'); $output .= $this->prepareCssForLess('popovers'); $output .= $this->prepareCssForLess('carousel'); // Utility classes $output .= $this->prepareCssForLess('utilities'); $output .= $this->prepareCssForLess('responsive-utilities'); $less = new \Less_Parser(); $less->SetImportDirs([base_path('vendor/twbs/bootstrap/less') => 'bootstrap']); $css = $less->parse($output, 'bootstrap.components.less')->getCss(); $minifier = new Minify\CSS(); $minifier->add($css); return $minifier->minify(); }
/** * Special compilation for template.css file when development mode is on * @param $path * @return bool */ public static function divide($path) { //check system self::requirement(); $parser = new Less_Parser(); $app = JFactory::getApplication(); $doc = JFactory::getDocument(); $tpl = T3_TEMPLATE; $theme = $app->getTemplate(true)->params->get('theme'); $is_rtl = $doc->direction == 'rtl' && strpos($path, 'rtl/') === false; $subdir = ($is_rtl ? 'rtl/' : '') . ($theme ? $theme . '/' : ''); $topath = T3_DEV_FOLDER . '/' . $subdir; $tofile = null; $root = JUri::root(true); //pattern $rimport = '@^\\s*\\@import\\s+"([^"]*)"\\s*;@im'; $rvarscheck = '@(base|base-bs3|bootstrap|' . preg_quote($tpl) . ')/less/(vars|variables|mixins)\\.less@'; $rexcludepath = '@(base|base-bs3|bootstrap|' . preg_quote($tpl) . ')/less/@'; $rimportvars = '@^\\s*\\@import\\s+".*(variables-custom|variables|vars|mixins)\\.less"\\s*;@im'; $rsplitbegin = '@^\\s*\\#'; $rsplitend = '[^\\s]*?\\s*{\\s*[\\r\\n]*\\s*content:\\s*"([^"]*)";\\s*[\\r\\n]*\\s*}@im'; $rswitchrtl = '@/less/(themes/[^/]*/)?@'; $kfilepath = 'less-file-path'; $kvarsep = 'less-content-separator'; $krtlsep = 'rtl-less-content'; if ($topath) { if (!is_dir(JPATH_ROOT . '/' . $topath)) { JFolder::create(JPATH_ROOT . '/' . $topath); } } // check path $realpath = realpath(JPATH_ROOT . '/' . $path); if (!is_file($realpath)) { return; } // get file content $content = JFile::read($realpath); //remove vars.less if (preg_match($rexcludepath, $path)) { $content = preg_replace($rimportvars, '', $content); } // check and add theme less if not is theme less if ($theme && strpos($path, 'themes/') === false) { $themepath = 'themes/' . $theme . '/' . basename($path); if (is_file(T3_TEMPLATE_PATH . '/less/' . $themepath)) { $content = $content . "\n@import \"{$themepath}\"; \n\n"; } } // split into array, separated by the import $split_contents = preg_split($rimport, $content, -1, PREG_SPLIT_DELIM_CAPTURE); //check if we need to rebuild $rebuild = false; $vars_lm = $app->getUserState('vars_last_modified', 0); $file_lm = @filemtime(JPATH_ROOT . '/' . $path); //check for this file and rtl $cssfile = $topath . str_replace('/', '.', $path) . '.css'; $css_lm = is_file(JPATH_ROOT . '/' . $cssfile) ? @filemtime(JPATH_ROOT . '/' . $cssfile) : -1; //rebuild? if ($css_lm < $vars_lm || $css_lm < $file_lm) { $rebuild = true; } else { $doc->addStylesheet($root . '/' . $cssfile); } //check for rebuild if this rtl overwrite file has just modified if (!$rebuild && $is_rtl) { $rtl_url = preg_replace('@/less/(themes/)?@', '/less/rtl/', $path); $rtl_lm = is_file(JPATH_ROOT . '/' . $rtl_url) ? @filemtime(JPATH_ROOT . '/' . $rtl_url) : 0; $rebuild = $css_lm < $rtl_lm; } if (!$rebuild) { $import = false; foreach ($split_contents as $chunk) { if ($import) { $import = false; $url = T3Path::cleanPath(dirname($path) . '/' . $chunk); if (is_file(JPATH_ROOT . '/' . $url)) { //$css_lm should be the same as templates.css $file_lm = @filemtime(JPATH_ROOT . '/' . $url); $theme_lm = -1; $rtl_lm = -1; $theme_rtl_lm = -1; if ($theme && strpos($url, 'themes/') === false) { $themepath = 'themes/' . $theme . '/' . basename($path); if (is_file(T3_TEMPLATE_PATH . '/less/' . $themepath)) { $theme_lm = @filemtime(T3_TEMPLATE_PATH . '/less/' . $themepath); } if ($is_rtl) { $rtlthemepath = preg_replace($rswitchrtl, '/less/rtl/' . $theme . '/', $url); if (is_file(JPATH_ROOT . '/' . $rtlthemepath)) { $theme_rtl_lm = @filemtime(JPATH_ROOT . '/' . $rtlthemepath); } } } if ($is_rtl) { $rtl_url = preg_replace('@/less/(themes/)?@', '/less/rtl/', $url); if (is_file(JPATH_ROOT . '/' . $rtl_url)) { $rtl_lm = @filemtime(JPATH_ROOT . '/' . $rtl_url); } } if (!is_file(JPATH_ROOT . '/' . $cssfile) || $css_lm < $vars_lm || $css_lm < $file_lm || $css_lm < $theme_lm || $css_lm < $rtl_lm || $css_lm < $theme_rtl_lm) { $rebuild = true; // rebuild for sure break; //no need further check } else { $doc->addStylesheet($root . '/' . $topath . str_replace('/', '.', $url) . '.css'); } } } else { $import = true; } } } // so, no need to rebuild? if (!$rebuild) { // add RTL css if needed if ($is_rtl) { $cssfile = $topath . str_replace('/', '.', str_replace('.less', '-rtl.less', $path)) . '.css'; if (is_file(JPATH_ROOT . '/' . $cssfile)) { $doc->addStylesheet($root . '/' . $cssfile); } } return false; } // variables & mixin $vars = self::getVars(); $output = ''; $importdirs = array(); // iterate to each chunk and add separator mark $import = false; foreach ($split_contents as $chunk) { if ($import) { $import = false; $url = T3Path::cleanPath(dirname($path) . '/' . $chunk); // ignore vars.less and variables.less if they are in template folder // cause there may have other css less file with the same name (eg. font awesome) if (preg_match($rvarscheck, $url)) { continue; } // remember this path when lookup for import $importdirs[dirname(JPATH_ROOT . '/' . $url)] = $root . '/' . dirname($url) . '/'; $output .= "#{$kfilepath}{content: \"{$url}\";}\n@import \"{$chunk}\";\n\n"; // check and add theme less if ($theme && strpos($url, 'themes/') === false) { $theme_rel = 'themes/' . $theme . '/' . basename($url); $theme_path = T3_TEMPLATE_PATH . '/less/' . $theme_rel; if (is_file($theme_path)) { $importdirs[dirname($theme_path)] = T3_TEMPLATE_URL . dirname($theme_rel) . '/'; $output .= "#{$kfilepath}{content: \"" . ('templates/' . T3_TEMPLATE . '/less/' . $theme_rel) . "\";}\n@import \"{$theme_rel}\";\n\n"; } } } else { $import = true; $chunk = trim($chunk); if ($chunk) { $output .= "#{$kfilepath}{content: \"{$path}\";}\n{$chunk}\n\n"; } } } // compile RTL overwrite when in RTL mode if ($is_rtl) { $rtlcontent = ''; // import rtl override $import = false; foreach ($split_contents as $chunk) { if ($import) { $import = false; $url = T3Path::cleanPath(dirname($path) . '/' . $chunk); // ignore vars.less and variables.less if they are in template folder // cause there may have other css less file with the same name (eg. font awesome) if (preg_match($rvarscheck, $url)) { continue; } // process import file $rtl_url = preg_replace('@/less/(themes/)?@', '/less/rtl/', $url); // is there overwrite file? if (!is_file(JPATH_ROOT . '/' . $rtl_url)) { continue; } // process import file $importcontent = JFile::read(JPATH_ROOT . '/' . $rtl_url); if (preg_match($rexcludepath, $rtl_url)) { $importcontent = preg_replace($rimportvars, '', $importcontent); } // remember this path when lookup for import if (preg_match($rimport, $importcontent)) { $importdirs[dirname(JPATH_ROOT . '/' . $rtl_url)] = $root . '/' . dirname($rtl_url) . '/'; } $rtlcontent .= "\n{$importcontent}\n\n"; // rtl theme overwrite if ($theme && strpos($url, 'themes/') === false) { $rtlthemepath = preg_replace($rswitchrtl, '/less/rtl/' . $theme . '/', $url); if (is_file(JPATH_ROOT . '/' . $rtlthemepath)) { // process import file $importcontent = JFile::read(JPATH_ROOT . '/' . $rtlthemepath); $rtlcontent .= "\n{$importcontent}\n\n"; $importdirs[dirname(JPATH_ROOT . '/' . $rtlthemepath)] = $root . '/' . dirname($rtlthemepath) . '/'; } } } else { $import = true; } } // override in template for this file $rtlpath = preg_replace($rswitchrtl, '/less/rtl/', $path); if (is_file(JPATH_ROOT . '/' . $rtlpath)) { // process import file $importcontent = JFile::read(JPATH_ROOT . '/' . $rtlpath); $rtlcontent .= "\n{$importcontent}\n\n"; $importdirs[dirname(JPATH_ROOT . '/' . $rtlpath)] = $root . '/' . dirname($rtlpath) . '/'; } // rtl theme if ($theme) { $rtlthemepath = preg_replace($rswitchrtl, '/less/rtl/' . $theme . '/', $path); if (is_file(JPATH_ROOT . '/' . $rtlthemepath)) { // process import file $importcontent = JFile::read(JPATH_ROOT . '/' . $rtlthemepath); $rtlcontent .= "\n{$importcontent}\n\n"; $importdirs[dirname(JPATH_ROOT . '/' . $rtlthemepath)] = $root . '/' . dirname($rtlthemepath) . '/'; } } if ($rtlcontent) { //rtl content will be treat as a new file $rtlfile = str_replace('.less', '-rtl.less', $path); $output = $output . "\n#{$kfilepath}{content: \"{$rtlfile}\";}\n\n#{$krtlsep}{content: \"separator\";}\n\n{$rtlcontent}\n\n"; } } // common place $importdirs[T3_TEMPLATE_PATH . '/less'] = T3_TEMPLATE_URL . '/less/'; // myself $importdirs[dirname(JPATH_ROOT . '/' . $path)] = $root . '/' . dirname($path) . '/'; // compile less to css using lessphp $parser->SetImportDirs($importdirs); $parser->SetFileInfo(JPATH_ROOT . '/' . $path, $root . '/' . dirname($path) . '/'); $source = $vars . "\n#{$kvarsep}{content: \"separator\";}\n" . $output; $parser->parse($source); $output = $parser->getCss(); //use cssjanus to transform the content if ($is_rtl) { if ($rtlcontent) { $output = preg_split($rsplitbegin . $krtlsep . $rsplitend, $output, -1, PREG_SPLIT_DELIM_CAPTURE); $rtlcontent = isset($output[2]) ? $output[2] : false; $output = $output[0]; } T3::import('jacssjanus/ja.cssjanus'); $output = JACSSJanus::transform($output, true); if ($rtlcontent) { $output = $output . "\n" . $rtlcontent; } } //update path and store to files $split_contents = preg_split($rsplitbegin . $kfilepath . $rsplitend, $output, -1, PREG_SPLIT_DELIM_CAPTURE); $file_contents = array(); $file = $path; //default $relpath = JURI::base(true) . '/' . dirname($file); $isfile = false; foreach ($split_contents as $chunk) { if ($isfile) { $isfile = false; $file = $chunk; $relpath = $topath ? T3Path::relativePath($topath, dirname($file)) : JURI::base(true) . '/' . dirname($file); } else { $file_contents[$file] = (isset($file_contents[$file]) ? $file_contents[$file] : '') . "\n" . ($file ? T3Path::updateUrl($chunk, $relpath) : $chunk) . "\n\n"; $isfile = true; } } if (!empty($file_contents)) { // remove the duplicate clearfix at the beginning $split_contents = preg_split($rsplitbegin . $kvarsep . $rsplitend, reset($file_contents)); // ignore first one, it's clearfix if (is_array($split_contents)) { array_shift($split_contents); } $file_contents[key($file_contents)] = implode("\n", $split_contents); //output the file to content and add to document foreach ($file_contents as $file => $content) { $cssfile = $topath . str_replace('/', '.', $file) . '.css'; JFile::write(JPATH_ROOT . '/' . $cssfile, $content); $doc->addStylesheet($root . '/' . $cssfile); } } }
protected static function compileCSS($sourceFileWithPath, $cssFileWithPath, $sourceFileType, $vars) { global $REX; if (!file_exists($sourceFileWithPath)) { return; } // get content of source file $sourceFileContent = file_get_contents($sourceFileWithPath); // strip comments out $sourceFileContent = self::stripCSSComments($sourceFileContent); // get file path $path = pathinfo($sourceFileWithPath); // compile source file to css try { if ($sourceFileType == 'scss') { // EP for scss string compilation $compiledCSS = rex_register_extension_point('SEO42_COMPILE_SCSS', $sourceFileContent, array('vars' => $vars)); if ($sourceFileContent == $compiledCSS) { // include compiler if (!class_exists('scssc')) { require_once $REX['INCLUDE_PATH'] . '/addons/seo42/classes/scssphp/scss.inc.php'; } $formatter = new scss_formatter(); $formatter->indentChar = "\t"; $formatter->close = "}" . PHP_EOL; $formatter->assignSeparator = ": "; $scss = new scssc(); $scss->addImportPath($path['dirname']); $scss->setFormatter($formatter); $compiledCSS = $scss->compile($sourceFileContent); } } else { // EP for less string compilation $compiledCSS = rex_register_extension_point('SEO42_COMPILE_LESS', $sourceFileContent, array('vars' => $vars, 'path' => $path['dirname'])); if ($sourceFileContent == $compiledCSS) { // include compiler if (!class_exists('Less_Parser')) { require_once $REX['INCLUDE_PATH'] . '/addons/seo42/classes/lessphp/Less.php'; } $parser = new Less_Parser(array()); $parser->SetImportDirs(array(realpath($path['dirname']) => '')); $parser->parse($sourceFileContent); $parser->ModifyVars($vars); $compiledCSS = $parser->getCss(); } } } catch (Exception $e) { echo '" />'; // close tag as we are probably in an open link tag in head section of website echo '<p style="margin: 5px;"><code>'; echo '<strong>' . strtoupper($sourceFileType) . ' Compile Error:</strong><br/>'; echo $e->getMessage(); echo '</code></p>'; exit; } // write css $fileHandle = fopen($cssFileWithPath, 'w'); fwrite($fileHandle, $compiledCSS); fclose($fileHandle); }
/** * Compile into a single string using PHPLess * * @access protected * @param mixed $contents * @return string */ protected function _compile_css() { $parser = new Less_Parser(); if (Arr::get($this->_config, 'minify_css', false)) { $parser->setOption('compress', true); } if (!empty($this->_import_dirs)) { $parser->SetImportDirs($this->_import_dirs); } foreach ($this->_paths['css'] as $file) { $file_location = $this->_get_file_location('css', $file); $parser->parseFile($file_location); } $css = $parser->getCss(); return $css; }
/** * Returns LESS compiler set up for use with MediaWiki * * @since 1.22 * @since 1.26 added $extraVars parameter * @param Config $config * @param array $extraVars Associative array of extra (i.e., other than the * globally-configured ones) that should be used for compilation. * @throws MWException * @return Less_Parser */ public static function getLessCompiler(Config $config, $extraVars = array()) { // When called from the installer, it is possible that a required PHP extension // is missing (at least for now; see bug 47564). If this is the case, throw an // exception (caught by the installer) to prevent a fatal error later on. if (!class_exists('Less_Parser')) { throw new MWException('MediaWiki requires the less.php parser'); } $parser = new Less_Parser(); $parser->ModifyVars(array_merge(self::getLessVars($config), $extraVars)); $parser->SetImportDirs(array_fill_keys($config->get('ResourceLoaderLESSImportPaths'), '')); $parser->SetOption('relativeUrls', false); $parser->SetCacheDir($config->get('CacheDirectory') ?: wfTempDir()); return $parser; }
/** * @param array $addPath * @return Less_Parser */ protected function _getProcessor($addPath = array()) { if (!class_exists('Less_Parser')) { require_once JPATH_ROOT . '/media/zoo/applications/jbuniversal/framework/libs/less.gpeasy.php'; } $options = array('compress' => 0, 'strictUnits' => 0, 'strictMath' => 0, 'relativeUrls' => 1, 'numPrecision' => 4, 'cache_method' => 0, 'sourceMap' => 0); $precessor = new Less_Parser($options); $paths = array_merge(array($this->_lessFull => $this->_lessRel, JPATH_ROOT => JUri::root()), $addPath); $precessor->SetImportDirs($paths); return $precessor; }
/** * Allows to define import directories for the less compiler. * * @param array $directories */ public function setImportDirectories(array $directories) { $this->compiler->SetImportDirs($directories); }