@@ -9,142 +9,160 @@ var glob = require('glob');
99var File = require ( 'vinyl' ) ;
1010
1111module . 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 = / \@ i m p o r t ( [ " ' ] ) ( .+ ?) \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 = / \@ i m p o r t ( [ " ' ] ) ( .+ ?) \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