View source
<?php
namespace Drupal\scss_compiler\Plugin\ScssCompiler;
use Drupal\scss_compiler\Plugin\ScssCompiler\Scssphp as Compiler;
use ScssPhp\ScssPhp\Version;
use Drupal\scss_compiler\ScssCompilerPluginBase;
use Drupal\Core\File\FileSystemInterface;
class ScssphpCompiler extends ScssCompilerPluginBase {
protected $parser;
public function init() {
$status = self::getStatus();
if ($status !== TRUE) {
throw new \Exception($status);
}
$this->parser = new Compiler();
$this->parser
->setFormatter($this
->getScssPhpFormatClass($this->scssCompiler
->getOption('output_format')));
$this->parser
->setEncoding(TRUE);
}
public static function getVersion() {
if (class_exists('ScssPhp\\ScssPhp\\Version')) {
return Version::VERSION;
}
return FALSE;
}
public static function getStatus() {
$compiler_class_exists = class_exists('ScssPhp\\ScssPhp\\Compiler');
if (!$compiler_class_exists && !file_exists(DRUPAL_ROOT . '/libraries/scssphp/scss.inc.php')) {
return t('ScssPhp Compiler library not found. Install it via composer "composer require scssphp/scssphp"');
}
if (!$compiler_class_exists) {
require_once DRUPAL_ROOT . '/libraries/scssphp/scss.inc.php';
if (!class_exists('ScssPhp\\ScssPhp\\Compiler')) {
$error_message = t('leafo/scssphp no longer supported. Update compiler library to scssphp/scssphp @url', [
'@url' => '(https://github.com/scssphp/scssphp/releases)',
]);
}
}
if (!empty($error_message)) {
return $error_message;
}
return TRUE;
}
public function compile(array $scss_file) {
$import_paths = [
dirname($scss_file['source_path']),
DRUPAL_ROOT,
[
$this,
'getImportNamespace',
],
];
if ($this->scssCompiler
->getAdditionalImportPaths()) {
$import_paths = array_merge($import_paths, $this->scssCompiler
->getAdditionalImportPaths());
}
$this->parser
->setImportPaths($import_paths);
$variables = $this->scssCompiler
->getVariables()
->getAll($scss_file['namespace'], $scss_file['source_path']);
$this->parser
->setVariables($variables);
$this->parser->assetsPath = isset($scss_file['assets_path']) ? $scss_file['assets_path'] : '';
$css_folder = dirname($scss_file['css_path']);
if ($this->scssCompiler
->getOption('sourcemaps')) {
$this->parser
->setSourceMap(Compiler::SOURCE_MAP_FILE);
$sourcemap_file = $css_folder . '/' . $scss_file['name'] . '.css.map';
$this->parser
->setSourceMapOptions([
'sourceMapWriteTo' => $sourcemap_file,
'sourceMapURL' => $scss_file['name'] . '.css.map',
'sourceMapBasepath' => DRUPAL_ROOT,
'sourceMapRootpath' => '/',
]);
}
$this->fileSystem
->prepareDirectory($css_folder, FileSystemInterface::CREATE_DIRECTORY);
$source_content = file_get_contents($scss_file['source_path']);
return $this->parser
->compile($source_content, $scss_file['source_path']);
}
public function checkLastModifyTime(array &$source_file) {
$last_modify_time = filemtime($source_file['source_path']);
$source_folder = dirname($source_file['source_path']);
$import = [];
$content = file_get_contents($source_file['source_path']);
preg_match_all('/@import(.*);/', $content, $import);
if (!empty($import[1])) {
foreach ($import[1] as $file) {
$file_path = trim($file, '\'" ');
$pathinfo = pathinfo($file_path);
$extension = '.scss';
$filename = $pathinfo['filename'];
$dirname = $pathinfo['dirname'] === '.' ? '' : $pathinfo['dirname'] . '/';
$file_path = $source_folder . '/' . $dirname . $filename . $extension;
$scss_path = $source_folder . '/' . $dirname . '_' . $filename . $extension;
if (file_exists($file_path) || file_exists($file_path = $scss_path)) {
$file_modify_time = filemtime($file_path);
if ($file_modify_time > $last_modify_time) {
$last_modify_time = $file_modify_time;
}
}
}
}
return $last_modify_time;
}
public function getImportNamespace($path) {
if (!preg_match('#([^/]+)/#', $path, $match)) {
return NULL;
}
$namespace = $match[1];
if (substr($namespace, 0, 1) === '@') {
$namespace = substr($namespace, 1);
}
$namespace_path = substr($path, strlen($match[0]));
$type = 'theme';
if ($this->moduleHandler
->moduleExists($namespace)) {
$type = 'module';
}
$path = @drupal_get_path($type, $namespace);
if (empty($path)) {
return NULL;
}
$base_path = DRUPAL_ROOT . '/' . $path . '/' . $namespace_path;
foreach ([
'',
'.scss',
'.css',
] as $extension) {
if ($path = realpath($base_path . $extension)) {
return $path;
}
}
return NULL;
}
private function getScssPhpFormatClass($format) {
switch ($format) {
case 'expanded':
return '\\ScssPhp\\ScssPhp\\Formatter\\Expanded';
case 'nested':
return '\\ScssPhp\\ScssPhp\\Formatter\\Nested';
case 'compact':
return '\\ScssPhp\\ScssPhp\\Formatter\\Compact';
case 'crunched':
return '\\ScssPhp\\ScssPhp\\Formatter\\Crunched';
default:
return '\\ScssPhp\\ScssPhp\\Formatter\\Compressed';
}
}
}