Vmeda.Online/gulp/task-combine-scss.js

165 lines
5.5 KiB
JavaScript

// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const gulp = require('gulp');
const through = require('through');
const bufferFrom = require('buffer-from');
const concat = require('gulp-concat');
const pathLib = require('path');
const fs = require('fs');
/**
* Task to combine scss into a single file.
*/
class CombineScssTask {
/**
* Finds the file and returns its content.
*
* @param capture Import file path.
* @param baseDir Directory where the file was found.
* @param paths Alternative paths where to find the imports.
* @param parsedFiles Already parsed files to reduce size of the result.
* @return Partially combined scss.
*/
getReplace(capture, baseDir, paths, parsedFiles) {
let parse = pathLib.parse(pathLib.resolve(baseDir, capture + '.scss'));
let file = parse.dir + '/' + parse.name;
if (file.slice(-3) === '.wp') {
console.log('Windows Phone not supported "' + capture);
// File was already parsed, leave the import commented.
return '// @import "' + capture + '";';
}
if (!fs.existsSync(file + '.scss')) {
// File not found, might be a partial file.
file = parse.dir + '/_' + parse.name;
}
// If file still not found, try to find the file in the alternative paths.
let x = 0;
while (!fs.existsSync(file + '.scss') && paths.length > x) {
parse = pathLib.parse(pathLib.resolve(paths[x], capture + '.scss'));
file = parse.dir + '/' + parse.name;
x++;
}
file = file + '.scss';
if (!fs.existsSync(file)) {
// File not found. Leave the import there.
console.log('File "' + capture + '" not found');
return '@import "' + capture + '";';
}
if (parsedFiles.indexOf(file) >= 0) {
console.log('File "' + capture + '" already parsed');
// File was already parsed, leave the import commented.
return '// @import "' + capture + '";';
}
parsedFiles.push(file);
const text = fs.readFileSync(file);
// Recursive call.
return this.scssCombine(text, parse.dir, paths, parsedFiles);
}
/**
* Run the task.
*
* @param done Function to call when done.
*/
run(done) {
const paths = [
'node_modules/ionic-angular/themes/',
'node_modules/font-awesome/scss/',
'node_modules/ionicons/dist/scss/'
];
const parsedFiles = [];
const self = this;
gulp.src([
'./src/theme/variables.scss',
'./node_modules/ionic-angular/themes/ionic.globals.*.scss',
'./node_modules/ionic-angular/themes/ionic.components.scss',
'./src/**/*.scss',
]).pipe(through(function(file) { // Combine them based on @import and save it to stream.
if (file.isNull()) {
return;
}
parsedFiles.push(file);
file.contents = bufferFrom(self.scssCombine(
file.contents, pathLib.dirname(file.path), paths, parsedFiles));
this.emit('data', file);
})).pipe(concat('combined.scss')) // Concat the stream output in single file.
.pipe(gulp.dest('.')) // Save file to destination.
.on('end', done);
}
/**
* Combine scss files with its imports
*
* @param content Scss string to treat.
* @param baseDir Directory where the file was found.
* @param paths Alternative paths where to find the imports.
* @param parsedFiles Already parsed files to reduce size of the result.
* @return Scss string with the replaces done.
*/
scssCombine(content, baseDir, paths, parsedFiles) {
// Content is a Buffer, convert to string.
if (typeof content != "string") {
content = content.toString();
}
// Search of single imports.
let regex = /@import[ ]*['"](.*)['"][ ]*;/g;
if (regex.test(content)) {
return content.replace(regex, (m, capture) => {
if (capture == "bmma") {
return m;
}
return this.getReplace(capture, baseDir, paths, parsedFiles);
});
}
// Search of multiple imports.
regex = /@import(?:[ \n]+['"](.*)['"][,]?[ \n]*)+;/gm;
if (regex.test(content)) {
return content.replace(regex, (m, capture) => {
let text = '';
// Divide the import into multiple files.
const captures = m.match(/['"]([^'"]*)['"]/g);
for (let x in captures) {
text += this.getReplace(captures[x].replace(/['"]+/g, ''), baseDir, paths, parsedFiles) + '\n';
}
return text;
});
}
return content;
}
}
module.exports = CombineScssTask;