Skip to content

Commit 105d03c

Browse files
committed
Works with absolute paths
1 parent e331b88 commit 105d03c

File tree

1 file changed

+119
-101
lines changed

1 file changed

+119
-101
lines changed

index.js

Lines changed: 119 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -9,142 +9,160 @@ var glob = require('glob');
99
var File = require('vinyl');
1010

1111
module.exports = function (loadPaths) {
12-
var graph = {}
12+
var graph = {};
1313

1414
// adds a sass file to a graph of dependencies
15-
var addToGraph = function(filepath, contents, parent) {
15+
var addToGraph = function (filepath, contents, parent) {
1616
var entry = graph[filepath] = graph[filepath] || {
1717
path: filepath,
1818
imports: [],
1919
importedBy: [],
2020
modified: fs.statSync(filepath).mtime
2121
};
2222
var imports = sassImports(contents());
23-
var cwd = path.dirname(filepath)
23+
var cwd = path.dirname(filepath);
24+
25+
imports = _.filter(imports, function(imp) { return imp.indexOf('.css') == -1});
2426

2527
for (var i in imports) {
2628
var resolved = sassResolve(imports[i], loadPaths.concat([cwd]));
2729
if (!resolved) return false;
2830

2931
// recurse into dependencies if not already enumerated
30-
if(!_.contains(entry.imports, resolved)) {
32+
if (!_.contains(entry.imports, resolved)) {
3133
entry.imports.push(resolved);
32-
addToGraph(resolved, function() {
34+
addToGraph(resolved, function () {
3335
return fs.readFileSync((path.extname(resolved) != "" ?
34-
resolved : resolved+".scss"),'utf8')
36+
resolved : resolved + ".scss"), 'utf8')
3537
}, filepath);
3638
}
3739
}
3840

3941
// add link back to parent
40-
if(parent != null) {
42+
if (parent != null) {
4143
entry.importedBy.push(parent);
4244
}
4345

4446
return true;
45-
}
47+
};
4648

4749
// visits all files that are ancestors of the provided file
48-
var visitAncestors = function(filepath, callback, visited) {
50+
var visitAncestors = function (filepath, callback, visited) {
4951
visited = visited || [];
5052
var edges = graph[filepath].importedBy;
5153

52-
for(var i in edges) {
53-
if(!_.contains(visited, edges[i])) {
54+
for (var i in edges) {
55+
if (!_.contains(visited, edges[i])) {
5456
visited.push(edges[i]);
5557
callback(graph[edges[i]]);
5658
visitAncestors(edges[i], callback, visited);
5759
}
5860
}
59-
}
61+
};
6062

6163
// parses the imports from sass
62-
var sassImports = function(content) {
63-
var re = /\@import (["'])(.+?)\1;/g, match = {}, results = [];
64-
65-
// strip comments
66-
content = new String(content).replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');
67-
68-
// extract imports
69-
while (match = re.exec(content)) {
70-
results.push(match[2]);
71-
}
72-
73-
return results;
74-
};
75-
76-
// resolve a relative path to an absolute path
77-
var sassResolve = function(path, loadPaths) {
78-
for(var p in loadPaths) {
79-
var scssPath = loadPaths[p] + "/" + path + ".scss"
80-
if (fs.existsSync(scssPath)) {
81-
return scssPath;
82-
}
83-
var partialPath = scssPath.replace(/\/([^\/]*)$/, '/_$1');
84-
if (fs.existsSync(partialPath)) {
85-
return partialPath
86-
}
87-
}
88-
89-
console.warn("failed to resolve %s from ", path, loadPaths)
90-
return false;
91-
}
92-
93-
// builds the graph
94-
_(loadPaths).forEach(function(path) {
95-
_(glob.sync(path+"/**/*.scss", {})).forEach(function(file){
96-
if(!addToGraph(file, function() { return fs.readFileSync(file) })) {
97-
console.warn("failed to add %s to graph", file)
98-
}
99-
});
100-
});
101-
102-
return through.obj(function (file, enc, cb) {
103-
if (file.isNull()) {
104-
this.push(file);
105-
return cb();
106-
}
107-
108-
if (file.isStream()) {
109-
this.emit('error',
110-
new gutil.PluginError('gulp-sass-graph', 'Streaming not supported'));
111-
return cb();
112-
}
113-
114-
fs.stat(file.path, function (err, stats) {
115-
if (err) {
116-
// pass through if it doesn't exist
117-
if (err.code === 'ENOENT') {
118-
this.push(file);
119-
return cb();
120-
}
121-
122-
this.emit('error', new gutil.PluginError('gulp-sass-graph', err));
123-
this.push(file);
124-
return cb();
125-
}
126-
127-
var relativePath = file.path.substr(file.cwd.length+1).replace(/\\/g, '/');
128-
console.log("processing %s", relativePath);
129-
130-
if(!graph[relativePath]) {
131-
addToGraph(relativePath, function() { return file.contents.toString('utf8') });
132-
}
133-
134-
this.push(file);
135-
136-
// push ancestors into the pipeline
137-
visitAncestors(relativePath, function(node){
138-
console.log("processing %s, which depends on %s", node.path, relativePath)
139-
this.push(new File({
140-
cwd: file.cwd,
141-
base: file.base,
142-
path: node.path,
143-
contents: fs.readFileSync(node.path)
144-
}));
145-
}.bind(this));
146-
147-
cb();
148-
}.bind(this));
149-
});
150-
};
64+
var sassImports = function (content) {
65+
var re = /\@import (["'])(.+?)\1\s*;/g, match = {}, results = [];
66+
67+
content = new String(content)
68+
// strip comments
69+
.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '')
70+
// concat multiline import separated with comma
71+
.replace(/,\s*(\n|\n\r|\r)/g, ',');
72+
73+
// extract imports
74+
while (match = re.exec(content)) {
75+
var matchedString = match[2];
76+
//multiline import support
77+
if (matchedString.search(',') > 0) {
78+
var multiImports = matchedString
79+
//remove quotation marks for splitting
80+
.replace(/'|"|\s/g, '')
81+
.split(',');
82+
for (var i in multiImports) {
83+
results.push(multiImports[i])
84+
}
85+
} else {
86+
results.push(match[2]);
87+
}
88+
}
89+
90+
return results;
91+
};
92+
93+
// resolve a relative path to an absolute path
94+
var sassResolve = function (path, loadPaths) {
95+
for (var p in loadPaths) {
96+
var scssPath = loadPaths[p] + "/" + path + ".scss";
97+
if (fs.existsSync(scssPath)) {
98+
return scssPath;
99+
}
100+
var partialPath = scssPath.replace(/\/([^\/]*)$/, '/_$1');
101+
if (fs.existsSync(partialPath)) {
102+
return partialPath
103+
}
104+
}
105+
106+
console.warn("failed to resolve %s from ", path, loadPaths);
107+
return false;
108+
};
109+
110+
// builds the graph
111+
_(loadPaths).forEach(function (path) {
112+
_(glob.sync(path + "/**/*.scss", {})).forEach(function (file) {
113+
if (!addToGraph(file, function () {
114+
return fs.readFileSync(file)
115+
})) {
116+
console.warn("failed to add %s to graph", file)
117+
}
118+
});
119+
});
120+
121+
return through.obj(function (file, enc, cb) {
122+
if (file.isNull()) {
123+
this.push(file);
124+
return cb();
125+
}
126+
127+
if (file.isStream()) {
128+
this.emit('error',
129+
new gutil.PluginError('gulp-sass-graph', 'Streaming not supported'));
130+
return cb();
131+
}
132+
133+
fs.stat(file.path, function (err, stats) {
134+
if (err) {
135+
// pass through if it doesn't exist
136+
if (err.code === 'ENOENT') {
137+
this.push(file);
138+
return cb();
139+
}
140+
141+
this.emit('error', new gutil.PluginError('gulp-sass-graph', err));
142+
this.push(file);
143+
return cb();
144+
}
145+
146+
if (!graph[file.path]) {
147+
addToGraph(relativePath, function () {
148+
return file.contents.toString('utf8')
149+
});
150+
}
151+
152+
this.push(file);
153+
154+
// push ancestors into the pipeline
155+
visitAncestors(file.path, function (node) {
156+
//console.log("processing %s, which depends on %s", node.path, file.path);
157+
this.push(new File({
158+
cwd: file.cwd,
159+
base: file.base,
160+
path: node.path,
161+
contents: new Buffer(fs.readFileSync(node.path, 'utf8'))
162+
}));
163+
}.bind(this));
164+
165+
cb();
166+
}.bind(this));
167+
});
168+
};

0 commit comments

Comments
 (0)