Valider 0ee4fe72 rédigé par cerdic's avatar cerdic
Parcourir les fichiers

Fix l'execution lente sur les postes de developpement avec xdebug actif

Pour cela il faut :
- avoir installé spip-cli,
- autoriser la commande exec() en php

On peut alors ajouter dans son fichier mes_options.php
define('_SCSSPHP_SPIP_CLI_COMPILE', true);
pour lancer la compilation des feuilles scssphp via spip-cli, qui utiliser php en mode cli, donc avec un autre php.ini sur lequel on n'a pas xdebug actif

Si spip-cli n'est pas dans /usr/local/bin/spip il est possible de definir son path
define('_SCSSPHP_SPIP_CLI_BIN', '/path/to/spip');

La compilation via spip-cli se fait exactement avec le même contexte et path que si elle est faite inline.
Seul petit inconvenient : avec ?var_mode=css il peut y avoir certains fichiers recompiles plusieurs fois si inclus plusieurs fois, car on a pas de persistence entre chaque compilation scss
mais ca reste beaucoup plus rapide qu'une compilation inline avec xdebug
parent ded638dd
Chargement en cours
Chargement en cours
Chargement en cours
Chargement en cours
+179 −0
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -57,3 +57,182 @@ class SPIPScssPhpCompiler extends ScssPhp\ScssPhp\Compiler {
	  return [ScssPhp\ScssPhp\Type::T_STRING, $quote, [$filepath ? $filepath : '']];
	}
}

/**
 * Compilation inline des scss, en appelant directement le compilateur
 *
 * @param string $style
 * @param array $contexte
 * @param array $cache_options
 * @param array $import_dirs
 * @param array $scss_vars
 * @return array
 *   [out, erreur]
 */
function scssphp_inline_compile($style, $contexte, $cache_options, $import_dirs, $scss_vars = []) {
	$log_pre = "scss_compile ";
	if (empty($_SERVER['HTTP_HOST'])) {
		$log_pre .= "[spip-cli] ";
	}

	spip_timer('scss_compile');

	// le compilateur ScssPhp\ScssPhp\Compiler compile le contenu
	$scss = new SPIPScssPhpCompiler($cache_options);
	$scss->setFormatter("ScssPhp\ScssPhp\Formatter\Expanded");

	// lui transmettre le path qu'il utilise pour les @import
	$scss->setImportPaths($import_dirs);

	// pouvoir importer des @import 'css/truc' sur fichier 'css/truc.scss.html'
	$scss->addImportPath(function($path) {
		// SPIP 3.0+
		if (function_exists('produire_fond_statique')) {
			if ($f = find_in_path($path . '.scss.html')) {
				$f = produire_fond_statique($path . '.scss', array('format' => 'scss'));
				$f = supprimer_timestamp($f);
				return $f;
			}
		}
		return null;
	});

	if ($scss_vars) {
		$scss->setVariables($scss_vars);
	}

	// Inline source maps
	// https://scssphp.github.io/scssphp/docs/#source-maps
	// https://github.com/leafo/scssphp/wiki/Source-Maps (deprecated)
	if (defined('_SCSS_SOURCE_MAP') and '_SCSS_SOURCE_MAP' == true) {
		$scss->setSourceMap(ScssPhp\ScssPhp\Compiler::SOURCE_MAP_INLINE);
		$scss->setSourceMapOptions(array(
			// This value is prepended to the individual entries in the 'source' field.
			'sourceRoot' => '',
			// an optional name of the generated code that this source map is associated with.
			'sourceMapFilename' => null,
			// url of the map
			'sourceMapURL' => null,
			// absolute path to a file to write the map to
			'sourceMapWriteTo' => null,
			// output source contents?
			'outputSourceFiles' => false,
			// base path for filename normalization
			'sourceMapRootpath' => '/',
			// base path for filename normalization
			// difference between file & url locations, removed from ALL source files in .map
			'sourceMapBasepath' => '/local/cache-scss/'
	  ));
	}

	try {
		$out = $scss->compile($style, isset($contexte['file']) ? $contexte['file'] : null);
		spip_log($log_pre. ' compile '.(isset($contexte['file'])?$contexte['file']:substr($style,0,100)).' :: '.spip_timer('scss_compile'), 'scssphp');
	}
	catch (Exception $ex) {
		// en cas d'erreur, on retourne du vide...
		spip_log($log_pre. ' SCSSPHP Compiler fatal error:'.$ex->getMessage(), 'scssphp'._LOG_ERREUR);

		$display_file = '';
		if (isset($contexte['file'])) {
			$display_file = $contexte['file'];
			if (strpos($ex->getMessage(), '.scss') !== false) {
				$display_file = basename($display_file);
			}
			$display_file= " fichier $display_file";
		}

		$erreur = 'SCSS : Echec compilation'
			. $display_file
			. '<br />' . $ex->getMessage();

		return ['', $erreur];
	}

	// si on a rien parse parce que fichier en cache, indiquer au moins le fichier source concerne dans l'en-tete
	$files = $scss->getParsedFiles();
	if (!$files and !empty($contexte['file'])) {
		$files = [$contexte['file'] => true];
	}

	if ($files and count($files)){
		$files = array_keys($files);
		$l = strlen(_DIR_RACINE);
		$lr = strlen(_ROOT_RACINE);
		foreach($files as $k=>$file){
			if ($l and strncmp($file,_DIR_RACINE,$l)==0){
				$files[$k] = substr($file,$l);
			}
			if ($lr and strncmp($file,_ROOT_RACINE,$lr)==0){
				$files[$k] = substr($file,$lr);
			}
		}
		$out = "/*\n#@".implode("\n#@",$files)."\n*"."/\n" . $out;
	}


	return [$out, null];
}


/**
 * Compilation cli des scss, en appelant directement spip cli via un exec
 * marche uniquement en local, mais utile sur les poste de dev dont xdebug est actif
 * car la compilation scssphp prend une plombe en xdebug et en passant en cli on la fait echapper
 *
 * @param string $style
 * @param array $contexte
 * @param array $cache_options
 * @param array $import_dirs
 * @param array $scss_vars
 * @return array
 *   [out, erreur]
 */
function scssphp_cli_compile($style, $contexte, $cache_options, $import_dirs, $scss_vars = []) {
	$spip_path_bin = "/usr/local/bin/spip";
	if (defined('_SCSSPHP_SPIP_CLI_BIN')) {
		$spip_path_bin = _SCSSPHP_SPIP_CLI_BIN;
	}

	$dir_taches = sous_repertoire(_DIR_TMP, 'scssphp');

	$tmp_file_name = $dir_taches . md5(creer_uniqid() . getmypid()) . ".json";

	$args = [
		'style' => $style,
		'contexte' => $contexte,
		'cache_options' => $cache_options,
		'import_dirs' => $import_dirs,
		'scss_vars' => $scss_vars,
	];

	file_put_contents($tmp_file_name, json_encode($args));

	$arg_tache = $tmp_file_name;
	$command = "";
	if (_DIR_RACINE) {
		$command = "cd "._DIR_RACINE." && ";
		$arg_tache = substr($arg_tache, strlen(_DIR_RACINE));
	}

	$command .= "$spip_path_bin scssphp:compile --tache=$arg_tache";
	$output = [];
	$return_var = 0;
	exec($command, $output, $return_var);
	$output = implode("\n", $output);

	// erreur !
	if ($return_var) {
		$output = trim($output);
		if ($return_var == 127) {
			$output .= "\nErreur #$return_var $spip_path_bin non trouvé : definissez le bon path pour spip-cli dans la constante _SCSSPHP_SPIP_CLI_BIN\n";
		}
		elseif (!$output) {
			$output = "Erreur #$return_var a l'execution de $spip_path_bin";
		}
		spip_log('scssphp_cli_compile compile Erreur #'.$return_var.' commande: ' . $command, 'scssphp' . _LOG_ERREUR);
		return ['', $output];
	}

	return [$output, null];
}
 No newline at end of file
+1 −1
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
<paquet
	prefix="scssphp"
	categorie="outil"
	version="2.4.5"
	version="2.5.0"
	etat="stable"
	compatibilite="[3.1.0;3.3.*]"
	logo="scssphp-64.png"
+10 −84
Numéro de ligne d'origine Numéro de ligne de diff Ligne de diff
@@ -32,8 +32,6 @@ function scss_cache_dir() {
function scss_compile($style, $contexte = array()) {
	include_spip('inc/scssphp_compiler');

	spip_timer('scss_compile');

	$import_dirs = _chemin();

	$cache_options = array(
@@ -48,98 +46,26 @@ function scss_compile($style, $contexte = array()) {
		$cache_options['forceRefresh'] = 'once';
	}

	// le compilateur ScssPhp\ScssPhp\Compiler compile le contenu
	$scss = new SPIPScssPhpCompiler($cache_options);
	$scss->setFormatter("ScssPhp\ScssPhp\Formatter\Expanded");

	// lui transmettre le path qu'il utilise pour les @import
	$scss->setImportPaths(_chemin());

	// pouvoir importer des @import 'css/truc' sur fichier 'css/truc.scss.html'
	$scss->addImportPath(function($path) {
		// SPIP 3.0+
		if (function_exists('produire_fond_statique')) {
			if ($f = find_in_path($path . '.scss.html')) {
				$f = produire_fond_statique($path . '.scss', array('format' => 'scss'));
				$f = supprimer_timestamp($f);
				return $f;
			}
		}
		return null;
	});
	// pipeline : scss_variables
	// Surcharger des variables depuis un plugin ou une configuration
	// les variables sont un tableau 'variable'=>'scss value'
	// ex : 'header'=> '(background:pink,color:white)'
	$scss_vars = pipeline('scss_variables',array());
	$scss->setVariables($scss_vars);

	// Inline source maps
	// https://scssphp.github.io/scssphp/docs/#source-maps
	// https://github.com/leafo/scssphp/wiki/Source-Maps (deprecated)
	if (defined('_SCSS_SOURCE_MAP') and '_SCSS_SOURCE_MAP' == true) {
		$scss->setSourceMap(ScssPhp\ScssPhp\Compiler::SOURCE_MAP_INLINE);
		$scss->setSourceMapOptions(array(
			// This value is prepended to the individual entries in the 'source' field.
			'sourceRoot' => '',
			// an optional name of the generated code that this source map is associated with.
			'sourceMapFilename' => null,
			// url of the map
			'sourceMapURL' => null,
			// absolute path to a file to write the map to
			'sourceMapWriteTo' => null,
			// output source contents?
			'outputSourceFiles' => false,
			// base path for filename normalization
			'sourceMapRootpath' => '/',
			// base path for filename normalization
			// difference between file & url locations, removed from ALL source files in .map
			'sourceMapBasepath' => '/local/cache-scss/'
	  ));
	}

	try {
		$out = $scss->compile($style, isset($contexte['file']) ? $contexte['file'] : null);
		spip_log('scss_compile compile '.(isset($contexte['file'])?$contexte['file']:substr($style,0,100)).' :: '.spip_timer('scss_compile'), 'scssphp');
	} catch (exception $ex) {
		// en cas d'erreur, on retourne du vide...
		spip_log('SCSS Compiler fatal error:'.$ex->getMessage(), 'scssphp'._LOG_ERREUR);
		$display_file = '';
		if (isset($contexte['file'])) {
			$display_file = $contexte['file'];
			if (strpos($ex->getMessage(), '.scss') !== false) {
				$display_file = basename($display_file);
			}
			$display_file= " fichier $display_file";
		}
		erreur_squelette(
			'SCSS : Echec compilation'
			. $display_file
			. '<br />' . $ex->getMessage()
		);
		return '';
	}

	// si on a rien parse parce que fichier en cache, indiquer au moins le fichier source concerne dans l'en-tete
	$files = $scss->getParsedFiles();
	if (!$files and !empty($contexte['file'])) {
		$files = [$contexte['file'] => true];
	}

	if ($files and count($files)){
		$files = array_keys($files);
		$l = strlen(_DIR_RACINE);
		$lr = strlen(_ROOT_RACINE);
		foreach($files as $k=>$file){
			if ($l and strncmp($file,_DIR_RACINE,$l)==0){
				$files[$k] = substr($file,$l);
			}
			if ($lr and strncmp($file,_ROOT_RACINE,$lr)==0){
				$files[$k] = substr($file,$lr);
	// si on developpe avec xdebug on peut utiliser un php cli pour compiler via spip cli et echapper au xdebug
	// car scssphp est tres lent avec xdebug
	if (defined('_SCSSPHP_SPIP_CLI_COMPILE') and _SCSSPHP_SPIP_CLI_COMPILE) {
		list($out, $erreur) = scssphp_cli_compile($style, $contexte, $cache_options, $import_dirs, $scss_vars);
	}
	else {
		list($out, $erreur) = scssphp_inline_compile($style, $contexte, $cache_options, $import_dirs, $scss_vars);
	}
		$out = "/*\n#@".implode("\n#@",$files)."\n*"."/\n" . $out;

	if ($erreur) {
		erreur_squelette($erreur);
		return '';
	}

	return $out;
}