165 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			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;
 |