Skip to content

Commit

Permalink
Merge pull request #14 from mervick/master
Browse files Browse the repository at this point in the history
Added alternative Scss parser with Compass framework support
  • Loading branch information
nizsheanez committed Jun 10, 2015
2 parents bb80598 + c3dd415 commit a1f831e
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 4 deletions.
170 changes: 170 additions & 0 deletions Scss.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php

namespace nizsheanez\assetConverter;

use Yii;

/**
* Class Scss
* @package nizsheanez\assetConverter
* @author Andrey Izman <[email protected]>
*/
class Scss extends Parser
{
/**
* @var bool compass support
*/
public $enableCompass = true;

/**
* @var array paths to import files
*/
public $importPaths = [];

/**
* @var bool if is true, compiler will place line numbers in your compiled output
*/
public $lineComments = false;

/**
* @var string output style
*/
public $outputStyle = 'nested';

/**
* @var array defined formatters
*/
protected $formatters = [
'compressed', 'crunched', 'expanded', 'nested',
];


/**
* Parse a Scss file and convert it into CSS
*
* @param string $src source file path
* @param string $dst destination file path
* @param array $options parser options
* @return mixed
* @throws \Exception
*/
public function parse($src, $dst, $options)
{
$this->importPaths = !empty($options['importPaths']) ? $options['importPaths'] : $this->importPaths;
$this->enableCompass = isset($options['enableCompass']) ? $options['enableCompass'] : $this->enableCompass;
$this->lineComments = isset($options['lineComments']) ? $options['lineComments'] : $this->lineComments;
$this->outputStyle = isset($options['outputStyle']) ? $options['outputStyle'] : $this->outputStyle;
$this->outputStyle = strtolower($this->outputStyle);

$parser = new \Leafo\ScssPhp\Compiler();
if (!empty($this->importPaths) && is_array($this->importPaths)) {
$paths = [''];
foreach ($this->importPaths as $path) {
$paths[] = Yii::getAlias($path);
}
$parser->setImportPaths($paths);
}

if (in_array($this->outputStyle, $this->formatters)) {
if ($this->lineComments && in_array($this->outputStyle, ['compressed', 'crunched'])) {
$this->lineComments = false;
}
$parser->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($this->outputStyle));
}

if ($this->enableCompass) {
new \scss_compass($parser);
}

if (!file_exists($src)) {
throw new \Exception("Failed to open file \"$src\"");
}

if ($this->lineComments) {
$content = self::insertLineComments($src, self::getRelativeFilename($src, $dst));
file_put_contents($dst, self::parseLineComments($parser->compile($content, $src)));
} else {
file_put_contents($dst, $parser->compile(file_get_contents($src), $src));
}
}

/**
* Returns the relative filename of $src to $dst
*
* @param string $src
* @param string $dst
* @return string
*/
protected static function getRelativeFilename($src, $dst) {
$src = explode('/', $src);
$dst = explode('/', $dst);
for ($index=1, $count=count($src); $index<$count; $index++) {
if (!isset($src[$index]) || !isset($dst[$index]) || $src[$index] !== $dst[$index]) {
break;
}
}
return str_repeat('../', count($dst)-$index-1) . implode('/', array_slice($src, $index));
}

/**
* Inserts the line numbers into comments
*
* @param string $src
* @param string $filename
* @return string
*/
protected static function insertLineComments($src, $filename)
{
$lines = explode("\n", preg_replace_callback('~/\*.+?\*/~sx',
function($m) {return str_repeat("\n", substr_count($m[0], "\n"));}, file_get_contents($src)));

foreach ($lines as $no => $line) {
$no++;
$newLine = '';
for ($pos = 0; ($pos = mb_strpos($line, '{')) !== false;) {
$comment = "/* line: $no, $filename */";
$newLine .= mb_substr($line, 0, $pos+1) . $comment;
$line = mb_substr($line, $pos+1);
}
if (!empty($newLine)) {
$lines[$no-1] = $newLine . $line;
}
}
return implode("\n", $lines);
}

/**
* Parses the line numbers comments and moves them into the header of the block
*
* @param string $content
* @return string
*/
protected static function parseLineComments($content)
{
$content = preg_replace('~(/\*.+?\*/)([\x0b-\x20]+)~sx', "\\1\n\\2", $content);
$lines = explode("\n", $content);
unset($content);
$begin = 0;
foreach ($lines as $id => $line) {
if (empty($line)) {
if ($id > 0 && $id === $begin+1) {
$begin = $id;
}
} elseif (strpos($line, '}') !== false) {
$begin = $id;
} elseif (strpos($line, '{') !== false) {
$begin = $id > 0 ? $id-1 : 0;
} elseif (strpos($line, '/*') !== false) {
unset($lines[$id]);
if ($begin > 0) {
for (; !isset($lines[$begin]); $begin--);
for ($next=$begin+1; !isset($lines[$next]); $next++);
$lines[$begin] .= "\n" . preg_replace('~^(\s+)*.+$~', '\1', $lines[$next]) . ltrim($line);
} else {
$lines[$begin] = preg_replace('~^(\s+)*.+$~', '\1', $lines[$begin]) . ltrim($line) . "\n" . $lines[$begin];
}
}
}
return implode("\n", $lines);
}
}
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "nizsheanez/yii2-asset-converter",
"description": "Less, Sass and Phamlp converter for Yii2. No system requires. yii2-composer support, Less autoupdate, customizing of output directory",
"description": "Less, Sass, Scss and Phamlp converter for Yii2. No system requires. yii2-composer support, Less autoupdate, customizing of output directory",
"type": "yii2-extension",
"keywords": ["yii", "yii2", "asset", "converter", "less", "sass", "phamlp"],
"keywords": ["yii", "yii2", "asset", "converter", "less", "sass", "scss", "compass", "phamlp"],
"license": "BSD-3-Clause",
"minimum-stability": "dev",
"authors": [
Expand All @@ -17,7 +17,9 @@
"yiisoft/yii2": "2.*",
"yiisoft/yii2-composer": "2.*",
"oyejorge/less.php": "1.7.0.*",
"richthegeek/phpsass": "dev-master"
"richthegeek/phpsass": "dev-master",
"leafo/scssphp": "dev-master",
"leafo/scssphp-compass": "dev-master"
},
"autoload": {
"psr-0": { "nizsheanez\\assetConverter\\": "" }
Expand Down
29 changes: 28 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,33 @@ But you can change it by destinationDir property from config
)
)
),
),
),

~~~

Also, for SCSS files you can use alternate configuration:

~~~php
'components' => array(
'assetManager' => array(
'converter'=>array(
// ...
'parsers' => array(
// ...
'scss' => array( // file extension to parse
'class' => 'nizsheanez\assetConverter\Scss',
'output' => 'css', // parsed output file type
'options' => array( // optional options
'enableCompass' => true, // default is true
'importPaths' => array(), // import paths, you may use path alias here,
// e.g., `['@path/to/dir', '@path/to/dir1', ...]`
'lineComments' => false, // if true — compiler will place line numbers in your compiled output
'outputStyle' => 'nested', // May be `compressed`, `crunched`, `expanded` or `nested`,
// see more at http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style
),
),
),
),
),
// ...
~~~

0 comments on commit a1f831e

Please sign in to comment.