Commit 5394fb9d authored by Cédric Anne's avatar Cédric Anne Committed by Johan Cwiklinski

Improve SCSS implementation

Fix cache key in dbug/no-debug mode
Always use theme in cache key
Migrate compilescss command to bin/console
Fix main style inclusion in find_num and login page
Fix compilation of plugin scss files via the add_css hook
Add sourcemap in debug mode
parent 81bb1c88
......@@ -46,7 +46,7 @@ echo "<html lang=\"{$CFG_GLPI["languages"][$_SESSION['glpilanguage']][3]}\">";
<title>GLPI</title>
<?php
echo Html::css($CFG_GLPI["root_doc"].'/css/styles.css');
echo Html::scss('main_styles');
echo Html::script($CFG_GLPI["root_doc"].'/script.js');
?>
......
......@@ -1293,15 +1293,22 @@ class Html {
foreach ($PLUGIN_HOOKS["add_css"] as $plugin => $files) {
$version = Plugin::getInfo($plugin, 'version');
if (is_array($files)) {
foreach ($files as $file) {
if (file_exists(GLPI_ROOT."/plugins/$plugin/$file")) {
echo Html::css("plugins/$plugin/$file", ['version' => $version]);
}
if (!is_array($files)) {
$files = [$files];
}
foreach ($files as $file) {
$filename = GLPI_ROOT."/plugins/$plugin/$file";
if (!file_exists($filename)) {
continue;
}
} else {
if (file_exists(GLPI_ROOT."/plugins/$plugin/$files")) {
echo Html::css("plugins/$plugin/$files", ['version' => $version]);
if ('scss' === substr(strrchr($filename, '.'), 1)) {
echo Html::scss("plugins/$plugin/$file", ['version' => $version]);
} else {
echo Html::css("plugins/$plugin/$file", ['version' => $version]);
}
}
}
......@@ -4834,7 +4841,7 @@ class Html {
* @since 0.85
* @since 9.2 Path is now relative to GLPI_ROOT. Add $minify parameter.
*
* @param sring $url File to include (raltive to GLPI_ROOT)
* @param string $url File to include (relative to GLPI_ROOT)
* @param array $options Array of HTML attributes
* @param boolean $minify Try to load minified file (defaults to true)
*
......@@ -4854,13 +4861,13 @@ class Html {
*
* @since 9.4
*
* @param sring $url File to include (raltive to GLPI_ROOT)
* @param string $url File to include (relative to GLPI_ROOT)
* @param array $options Array of HTML attributes
*
* @return string CSS link tag
**/
static function scss($url, $options = []) {
$prod_file = implode('/', self::getScssCompilePath($url));
$prod_file = self::getScssCompilePath($url);
if (file_exists($prod_file) && $_SESSION['glpi_use_mode'] != Session::DEBUG_MODE) {
$url = self::getPrefixedUrl(str_replace(GLPI_ROOT, '', $prod_file));
......@@ -6588,50 +6595,56 @@ class Html {
* @return string
*/
public static function compileScss($args) {
global $GLPI_CACHE;
global $CFG_GLPI, $GLPI_CACHE;
$ckey = isset($args['v']) ? $args['v'] : GLPI_SCHEMA_VERSION;
$scss = new Compiler();
if ($_SESSION['glpi_use_mode'] != Session::DEBUG_MODE && !isset($args['debug'])) { // mode debug
$ckey .= '_debug';
$scss->setFormatter('Leafo\ScssPhp\Formatter\Crunched');
$scss->setFormatter('Leafo\ScssPhp\Formatter\Crunched');
if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE || isset($args['debug'])) {
$ckey .= '_sourcemap';
$scss->setSourceMap(Compiler::SOURCE_MAP_INLINE);
$scss->setSourceMapOptions(
[
'sourceMapBasepath' => GLPI_ROOT . '/',
'sourceRoot' => $CFG_GLPI['root_doc'] . '/',
]
);
}
$paths = [
GLPI_ROOT . '/css/',
GLPI_ROOT . '/css/palettes/',
];
if (!isset($args['file']) || $args['file'] == 'main_styles') {
$import = '@import "styles.scss";';
$import = '@import "css/styles";';
if (isset($_SESSION['glpihighcontrast_css'])
&& $_SESSION['glpihighcontrast_css']) {
$ckey .= '_highcontrast';
$import .= '@import "highcontrast";';
$import .= '@import "css/highcontrast";';
}
// CSS theme
$theme = 'auror';
if (isset($_SESSION["glpipalette"])) {
$ckey .= '_' . $_SESSION['glpipalette'];
$theme = $_SESSION['glpipalette'];
}
$import .= '@import "'.$theme.'";';
$ckey .= '_' . $theme;
$import .= '@import "css/palettes/'.$theme.'";';
} else {
$ckey .= '_' . md5($args['file']);
$exploded = explode('/', $args['file']);
$file = array_pop($exploded);
if (count($exploded) == 1) {
$path = realpath(GLPI_ROOT . '/plugins/' . $exploded[0] . '/css');
if ($path && Toolbox::startsWith(GLPI_ROOT . '/plugins/', $path)) {
$paths[] = $path;
}
$filename = realpath(GLPI_ROOT . '/' . $args['file']);
if (!Toolbox::startsWith($filename, realpath(GLPI_ROOT))) {
// Prevent import of a file from ouside GLPI dir
return '';
}
if (!Toolbox::endsWith($args['file'], '.scss')) {
// Prevent include of file if ext is not .scss
$args['file'] .= '.scss';
}
$import = '@import "' . $args['file'] . '.scss";';
$import = '@import "' . $args['file'] . '";';
}
$scss->setImportPaths($paths);
$scss->addImportPath(GLPI_ROOT);
$ckey = md5($ckey);
if ($GLPI_CACHE->has($ckey) && !isset($args['reload']) && !isset($args['nocache'])) {
......@@ -6647,14 +6660,26 @@ class Html {
}
/**
* Get scss compilation informations (directory and file name
* Get scss compilation path for given file.
*
* @return array
*/
public static function getScssCompilePath($file) {
return [
'dir' => GLPI_ROOT . '/css/compiled/',
'file' => str_replace('/', '_', $file) . '.min.css'
];
return implode(
DIRECTORY_SEPARATOR,
[
self::getScssCompileDir(),
str_replace('/', '_', $file) . '.min.css',
]
);
}
/**
* Get scss compilation directory.
*
* @return string
*/
public static function getScssCompileDir() {
return GLPI_ROOT . '/css/compiled';
}
}
......@@ -83,7 +83,7 @@ if (!file_exists(GLPI_CONFIG_DIR . "/config_db.php")) {
echo "<meta name='viewport' content='width=device-width, initial-scale=1'/>";
// Appel CSS
echo Html::css('css/styles', [], true, true);
echo Html::scss('main_styles');
// font awesome icons
echo Html::css('lib/font-awesome-5.4.1/css/all.min.css');
......
#!/bin/php
<?php
/**
* ---------------------------------------------------------------------
* GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2015-2017 Teclib' and contributors.
* Copyright (C) 2015-2018 Teclib' and contributors.
*
* http://glpi-project.org
*
......@@ -31,40 +30,91 @@
* ---------------------------------------------------------------------
*/
function displayUsage() {
die("usage: ".$_SERVER['argv'][0]." [ --file=main_styles ]\n");
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
chdir(__DIR__);
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
if (!defined('GLPI_ROOT')) {
define('GLPI_ROOT', realpath('..'));
}
class CompileScssCommand extends Command {
/**
* Error code returned if unable to write compiled CSS.
*
* @var integer
*/
const ERROR_UNABLE_TO_WRITE_COMPILED_FILE = 1;
if ($_SERVER['argc']>1) {
for ($i=1; $i<count($_SERVER['argv']); $i++) {
$it = explode("=", $argv[$i], 2);
$it[0] = preg_replace('/^--/', '', $it[0]);
$args[$it[0]] = (isset($it[1]) ? $it[1] : true);
protected function configure() {
parent::configure();
$this->setName('glpi:build:compile_scss');
$this->setAliases(['build:compile_scss']);
$this->setDescription('Compile SCSS file.');
$this->addOption(
'file',
'f',
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
'File to compile (compile main style by default)'
);
}
}
include_once GLPI_ROOT . '/inc/includes.php';
protected function initialize(InputInterface $input, OutputInterface $output) {
//manage write path
$scssc_path = Html::getScssCompilePath(isset($args['file']) ? $args['file'] : 'main_styles');
$destdir = $scssc_path['dir'];
$filename = $scssc_path['file'];
$compile_directory = Html::getScssCompileDir();
if (!file_exists($destdir)) {
mkdir($destdir);
} else if (!is_dir($destdir)) {
throw new \RuntimeException('Check your dir parameter!');
}
if (!@is_dir($compile_directory) && !@mkdir($compile_directory)) {
throw new RuntimeException(
sprintf(
'Destination directory "%s" cannot be accessed.',
$compile_directory
)
);
}
}
protected function execute(InputInterface $input, OutputInterface $output) {
$files = $input->getOption('file');
if (empty($files)) {
$files[] = 'main_styles'; // Compile main styles if no file option is set.
}
//do not use caceh here
$args['nocache'] = true;
$css = Html::compileScss($args);
foreach ($files as $file) {
$output->writeln(
'<comment>' . sprintf('Processing "%s".', $file) . '</comment>',
OutputInterface::VERBOSITY_VERBOSE
);
//write to file
file_put_contents($destdir . '/' . $filename, $css);
$compiled_path = Html::getScssCompilePath($file);
$css = Html::compileScss(
[
'file' => $file,
'nocache' => true,
]
);
if (@file_put_contents($compiled_path, $css)) {
$message = sprintf('"%s" compiled successfully in "%s".', $file, $compiled_path);
$output->writeln(
'<info>' . $message . '</info>',
OutputInterface::VERBOSITY_NORMAL
);
} else {
$message = sprintf('Unable to write compiled CSS in "%s".', $compiled_path);
$output->writeln(
'<error>' . $message . '</error>',
OutputInterface::VERBOSITY_QUIET
);
return self::ERROR_UNABLE_TO_WRITE_COMPILED_FILE;
}
}
return 0; // Success
}
}
......@@ -87,7 +87,7 @@ echo "Minify stylesheets and javascripts"
$INIT_PWD/vendor/bin/robo minify --load-from tools
echo "Compile SCSS"
$INIT_PWD/scripts/compile_scss
$INIT_PWD/bin/console build:compile_scss
echo "Compile locale files"
./tools/locale/update_mo.pl
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment