2015/05/27

Gulp 處理資料夾內的scss 並 concat 成資料夾名稱

事情是這樣的
我想要把每個view的scss都單獨一個檔案
然後相關的放在同個資料夾,檢單來說就是跟著Controller走
然後輸出時利用gulp編譯後自動合併成資料夾名稱引用
這樣比較不容易動到其他的scss

目錄結構:
\resource\assets\sass
|    \memo
|    |    list.scss
|    |    show.scss
|    \article
|    |     list.scss
|    |     show.scss

\public\css

目標是執行完gulp之後
public\css會出現 memo.css, article.css
是由底下的 *.scss 編譯後合併
試了很多種方法最後終於成功了

======================================

由於gulp-concat的檔名需要根據資料夾
網路的範例都是寫死檔名
如果需要用變數處理,需要重新傳回 stream 給 gulp 處理
檔名的部分是使用 gulp-tap 抓取
gulp.task('sassIn', function () {
 var srcPath = 'resources/assets/sass';
 var outputPath = 'public/css';

 return gulp.src(srcPath + '/**/')
  .pipe(tap(function(file, t) {
         if ( file.isDirectory() && file.relative.length) {                
                var name = file.relative + '.css';

                console.log("processing folder:", file.path);
                console.log("\toutput filename is:", name);

                return gulp.src( path.join(file.path , '/*.scss') )
                   .pipe(tap(function(file, t) {
                    console.log("\tprocessing file:", file.path);
                   }))
                   .pipe(sass().on('error', sass.logError))
                   .pipe(gulpif(util.env.production, minifier()))
                      .pipe(concat(name))
                      .pipe(gulp.dest(outputPath));
            }
     }));  
});

如果處理的檔案是目錄的話,
而且該目錄是位於srcPath下(直接指srcPath 的 file.path會沒東西)
就重新傳回一個gulp並且處理

=====================================

搭配laravel elixir使用
elixir(function(mix) {
  mix.task('sassIn');
});

BTW如果要使用elixir的module
需要多加路徑去指(這個我也卡很久)
var requireBase = './node_modules/laravel-elixir/node_modules/';
var util        = require(requireBase + 'gulp-util');
var gulpif      = require(requireBase + 'gulp-if');
var minifyCss   = require(requireBase + 'gulp-minify-css');
var sass        = require(requireBase + 'gulp-sass');
var concat      = require(requireBase + 'gulp-concat');
var minifier    = require(requireBase + 'gulp-minify-css');

 

======================================

留一下紀念我寫的無用code XDD
function sassIn(mix, src, output, options){
 var srcPath = 'resources/assets/sass';
 var compilePath = 'resources/assets/sass/compiled';
 var outputPath = 'public/css';
 if( src ){ srcPath = path.join(srcPath, src); } 
 if( output ){ outputPath = path.join(outputPath, output) };

 //get src dir's sub dirs
 var dirs = readDirFiles(srcPath, null, true);
 for(i in dirs){
  var dir = dirs[i];
  if( dir == 'compiled') continue;
  var currentCompiledDir = path.join(compilePath, dir);
  var currentDir = path.join(srcPath, dir);
  var outputFile = path.join(outputPath, dir) + '.css';

  //check file exists
  try{ console.log('unlinkSync', outputFile); console.log(fs.unlinkSync(outputFile)); console.log('unlinkSync done');} catch(err){ /*just igone it*/ }
  sleep(1000);

  //loop subdir files to sass
  var files = readDirFiles(currentDir, function(file){
   filepath = path.join(dir, file);
   mix.sass(filepath, currentCompiledDir);
  });

  sleep(1000);

  //merge under subdir
  console.log('stylesIn');
  mix.stylesIn(currentCompiledDir, outputFile);
  console.log('stylesIn end');
 }
}

function readDirFiles(srcPath, cb, onlyDir){
 var dirFiles = [];
 var files = fs.readdirSync(srcPath);
 for(var i in files){
  var file = files[i];
  var filepath = path.join(srcPath, file);

  var isDir = fs.statSync(filepath).isDirectory();
  if( (onlyDir && !isDir) || (!onlyDir && isDir) ){
   continue; 
  }

  dirFiles.push(file);
  if(cb) cb(file);
 }
 return dirFiles;
}
function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

1 則留言: