From b9e46c932979d39ca99b9e37135355b86628c008 Mon Sep 17 00:00:00 2001 From: lubo Date: Fri, 16 Jan 2015 00:44:46 +0800 Subject: [PATCH] Update index.js 1. add file.contents to files dependent on the input file before this.push Some plugins, such as gulp-compass, will check if ```file.isNull()``` before compile input files. If there is no content in the file, those plugins will skip them. 2. refine function sassImports sass support import multiple files in one @import expression, such as ```'@import "a","b"'```, sassImports is refined to support such expression --- index.js | 222 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 120 insertions(+), 102 deletions(-) diff --git a/index.js b/index.js index b72ce76..5de259c 100644 --- a/index.js +++ b/index.js @@ -9,139 +9,157 @@ var glob = require('glob'); var File = require('vinyl'); module.exports = function (loadPaths) { - var graph = {} - - // adds a sass file to a graph of dependencies - var addToGraph = function(filepath, contents, parent) { - var entry = graph[filepath] = graph[filepath] || { - path: filepath, - imports: [], - importedBy: [], - modified: fs.statSync(filepath).mtime - }; - var imports = sassImports(contents()); - var cwd = path.dirname(filepath) - - for (var i in imports) { - var resolved = sassResolve(imports[i], loadPaths.concat([cwd])); - if (!resolved) return false; - - // recurse into dependencies if not already enumerated - if(!_.contains(entry.imports, resolved)) { - entry.imports.push(resolved); - addToGraph(resolved, function() { - return fs.readFileSync((path.extname(resolved) != "" ? - resolved : resolved+".scss"),'utf8') - }, filepath); - } - } - - // add link back to parent - if(parent != null) { - entry.importedBy.push(parent); - } - - return true; - } - - // visits all files that are ancestors of the provided file - var visitAncestors = function(filepath, callback, visited) { - visited = visited || []; - var edges = graph[filepath].importedBy; - - for(var i in edges) { - if(!_.contains(visited, edges[i])) { - visited.push(edges[i]); - callback(graph[edges[i]]); - visitAncestors(edges[i], callback, visited); - } - } - } - - // parses the imports from sass - var sassImports = function(content) { - var re = /\@import (["'])(.+?)\1;/g, match = {}, results = []; + var graph = {}; + + // adds a sass file to a graph of dependencies + var addToGraph = function (filepath, contents, parent) { + var entry = graph[filepath] = graph[filepath] || { + path: filepath, + imports: [], + importedBy: [], + modified: fs.statSync(filepath).mtime + }; + var imports = sassImports(contents()); + var cwd = path.dirname(filepath); + + for (var i in imports) { + var resolved = sassResolve(imports[i], loadPaths.concat([cwd])); + if (!resolved) return false; + + // recurse into dependencies if not already enumerated + if (!_.contains(entry.imports, resolved)) { + entry.imports.push(resolved); + addToGraph(resolved, function () { + return fs.readFileSync((path.extname(resolved) != "" ? + resolved : resolved + ".scss"), 'utf8') + }, filepath); + } + } - // strip comments - content = new String(content).replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, ''); + // add link back to parent + if (parent != null) { + entry.importedBy.push(parent); + } + + return true; + }; + + // visits all files that are ancestors of the provided file + var visitAncestors = function (filepath, callback, visited) { + visited = visited || []; + var edges = graph[filepath].importedBy; + + for (var i in edges) { + if (!_.contains(visited, edges[i])) { + visited.push(edges[i]); + callback(graph[edges[i]]); + visitAncestors(edges[i], callback, visited); + } + } + }; + + // parses the imports from sass + var sassImports = function (content) { + var re = /\@import (["'])(.+?)\1\s*;/g, match = {}, results = []; - // extract imports - while (match = re.exec(content)) { - results.push(match[2]); - } + content = new String(content) + // strip comments + .replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '') + // concat multiline import separated with comma + .replace(/,\s*(\n|\n\r|\r)/g, ','); + + // extract imports + while (match = re.exec(content)) { + var matchedString = match[2]; + //multiline import support + if (matchedString.search(',') > 0) { + var multiImports = matchedString + //remove quotation marks for splitting + .replace(/'|"|\s/g, '') + .split(','); + for (var i in multiImports) { + results.push(multiImports[i]) + } + } else { + results.push(match[2]); + } + } - return results; + return results; }; // resolve a relative path to an absolute path - var sassResolve = function(path, loadPaths) { - for(var p in loadPaths) { - var scssPath = loadPaths[p] + "/" + path + ".scss" - if (fs.existsSync(scssPath)) { - return scssPath; - } - var partialPath = scssPath.replace(/\/([^\/]*)$/, '/_$1'); - if (fs.existsSync(partialPath)) { - return partialPath - } - } - - console.warn("failed to resolve %s from ", path, loadPaths) - return false; - } + var sassResolve = function (path, loadPaths) { + for (var p in loadPaths) { + var scssPath = loadPaths[p] + "/" + path + ".scss"; + if (fs.existsSync(scssPath)) { + return scssPath; + } + var partialPath = scssPath.replace(/\/([^\/]*)$/, '/_$1'); + if (fs.existsSync(partialPath)) { + return partialPath + } + } + + console.warn("failed to resolve %s from ", path, loadPaths); + return false; + }; // builds the graph - _(loadPaths).forEach(function(path) { - _(glob.sync(path+"/**/*.scss", {})).forEach(function(file){ - if(!addToGraph(file, function() { return fs.readFileSync(file) })) { - console.warn("failed to add %s to graph", file) - } + _(loadPaths).forEach(function (path) { + _(glob.sync(path + "/**/*.scss", {})).forEach(function (file) { + if (!addToGraph(file, function () { + return fs.readFileSync(file) + })) { + console.warn("failed to add %s to graph", file) + } }); - }); + }); return through.obj(function (file, enc, cb) { if (file.isNull()) { - this.push(file); - return cb(); + this.push(file); + return cb(); } if (file.isStream()) { this.emit('error', - new gutil.PluginError('gulp-sass-graph', 'Streaming not supported')); + new gutil.PluginError('gulp-sass-graph', 'Streaming not supported')); return cb(); } fs.stat(file.path, function (err, stats) { if (err) { - // pass through if it doesn't exist - if (err.code === 'ENOENT') { - this.push(file); - return cb(); - } - - this.emit('error', new gutil.PluginError('gulp-sass-graph', err)); + // pass through if it doesn't exist + if (err.code === 'ENOENT') { this.push(file); return cb(); + } + + this.emit('error', new gutil.PluginError('gulp-sass-graph', err)); + this.push(file); + return cb(); } - var relativePath = file.path.substr(file.cwd.length+1).replace(/\\/g, '/'); + var relativePath = file.path.substr(file.cwd.length + 1); console.log("processing %s", relativePath); - if(!graph[relativePath]) { - addToGraph(relativePath, function() { return file.contents.toString('utf8') }); + if (!graph[relativePath]) { + addToGraph(relativePath, function () { + return file.contents.toString('utf8') + }); } this.push(file); - // push ancestors into the pipeline - visitAncestors(relativePath, function(node){ - console.log("processing %s, which depends on %s", node.path, relativePath) - this.push(new File({ - cwd: file.cwd, - base: file.base, - path: node.path, - contents: fs.readFileSync(node.path) - })); + visitAncestors(relativePath, function (node) { + console.log("processing %s, which depends on %s", node.path, relativePath); + this.push(new File({ + cwd: file.cwd, + base: file.base, + path: node.path, + contents: new Buffer(node.path) + })); }.bind(this)); cb();