1- /// <reference path="typings/node/node.d.ts" />
21"use strict" ;
3- var gutil = require ( "gulp-util" ) ;
42var through = require ( "through2" ) ;
5- var format = require ( "util" ) . format ;
63var path = require ( "path" ) ;
7- var deepExtend = require ( 'deep-extend' ) ;
8- var isMatch = require ( "./helper" ) . isMatch ;
9- var resolvePath = require ( "./helper" ) . resolvePath ;
10- var trim = require ( "./helper" ) . trim ;
11- var PathObject = require ( "./pathObject" ) ;
12- var Chunk = require ( "./chunk" ) ;
4+ var deepExtend = require ( "deep-extend" ) ;
5+ var fs = require ( "fs" ) ;
6+ var pify = require ( "pify" ) ;
7+ var gutil = require ( "gulp-util" ) ;
8+ var collect = require ( "collect-stream" ) ;
9+ var hh = require ( "http-https" ) ;
10+ var minimatch = require ( "minimatch" ) ;
11+ var phpfn = require ( "phpfn" ) ;
12+
13+ var PLUGIN_NAME = "gulp-cssimport" ;
14+ var readFile = pify ( fs . readFile ) ;
15+ var trim = phpfn ( "trim" ) ;
16+ var format = require ( "util" ) . format ;
1317
1418var defaults = {
1519 extensions : null ,
@@ -20,12 +24,6 @@ var defaults = {
2024 } ,
2125 limit : 5000
2226} ;
23- Object . defineProperty ( defaults , "directory" , {
24- enumerable : true ,
25- get : function ( ) {
26- return process . cwd ( ) ;
27- }
28- } ) ;
2927
3028module . exports = function cssImport ( options ) {
3129
@@ -40,109 +38,141 @@ module.exports = function cssImport(options) {
4038 var stream ;
4139 var cssCount = 0 ;
4240
43- function fileContents ( data , encoding , callback ) {
41+ function fileContents ( vinyl , encoding , callback ) {
42+ // console.log('fileContents ' , vinyl.path);
43+
4444 if ( ! stream ) {
4545 stream = this ;
4646 }
47- var chunk = Chunk . create ( data , { directory : options . directory } ) ;
48- //console.log("chunk.isVinyl", chunk.isVinyl);
4947 // https://github.com/kevva/import-regex/
50- var regex = '(?:@import)(?:\\s)(?:url)?(?:(?:(?:\\()(["\'])?(?:[^"\')]+)\\1(?:\\))|(["\'])(?:.+)\\2)(?:[A-Z\\s])*)+(?:;)' ;
48+ var regex = '(?:@import)(?:\\s)(?:url)?(?:(?:(?:\\()(["\'])?(?:[^"\')]+)\\1(?:\\))|(["\'])(?:.+)\\2)(?:[A-Z\\s])*)+(?:;)' ; // eslint-disable-line
5149 var importRe = new RegExp ( regex , "gi" ) ;
5250 var match ;
53- var fileArray = [ ] ;
54- var lastPos = 0 ;
55- var count = 0 ;
56- var contents = chunk . getContents ( ) ;
51+ var file = [ ] ;
52+ var lastpos = 0 ;
53+ var promises = [ ] ;
54+ var contents = vinyl . contents . toString ( ) ;
5755 while ( ( match = importRe . exec ( contents ) ) !== null ) {
5856 var match2 = / @ i m p o r t \s + (?: u r l \( ) ? ( .+ (? = [ ' " \) ] ) ) (?: \) ) ? .* / ig. exec ( match [ 0 ] ) ;
59- var filePath = trim ( match2 [ 1 ] , "'\"" ) ;
60- //console.log(filePath, isMatch(filePath, options));
61- if ( ! isMatch ( filePath , options ) ) {
57+ var importPath = trim ( match2 [ 1 ] , "'\"" ) ;
58+ if ( ! isMatch ( importPath , options ) ) {
6259 continue ;
6360 }
64- fileArray [ fileArray . length ] = contents . slice ( lastPos , match . index ) ;
65- var index = fileArray . length ;
66- var pathObject = new PathObject ( {
67- index : index ,
68- path : filePath ,
69- directory : chunk . getDirectory ( )
70- } ) ;
71- fileArray [ index ] = format ( "importing file %j" , pathObject ) ;
72- lastPos = importRe . lastIndex ;
61+ file [ file . length ] = contents . slice ( lastpos , match . index ) ;
62+ var index = file . length ;
63+ file [ index ] = format ( "importing file %s from %s" , importPath , vinyl . relative ) ;
64+ lastpos = importRe . lastIndex ;
7365 // Start resolving.
74- // console.log("Start resolving", cssCount++, pathObject);
7566 if ( ++ cssCount > options . limit ) {
7667 stream . emit ( "error" , new Error ( "Exceed limit. Recursive include?" ) ) ;
7768 return ;
7869 }
79- count ++ ;
80- resolvePath ( pathObject , onResolvePath ) ;
81- }
8270
83- function onResolvePath ( err , data , pathObject ) {
84- if ( err ) {
85- console . trace ( err ) ;
86- throw err ;
87- // todo: Make it more realiable.
88- // callback(err);
89- // return;
90- }
91- fileArray [ pathObject . index ] = data ;
92- count -- ;
93- if ( count === 0 ) {
94- var state = { directory : pathObject . directory } ;
95- if ( ! pathObject . isUrl ( ) ) {
96- state . directory = pathObject . getPathDirectory ( ) ;
71+ ( function ( index ) {
72+ if ( ! isUrl ( importPath ) ) {
73+ var importFile = path . resolve ( path . dirname ( vinyl . path ) , importPath ) ;
74+ // console.log('importFile %s from %s' , importFile, vinyl.path);
75+ promises . push ( readFile ( importFile , "utf8" ) . then ( function ( data ) {
76+ return { index : index , importFile : importFile , data : data } ;
77+ } ) ) ;
78+ } else {
79+ promises [ promises . length ] = new Promise ( function ( resolve , reject ) {
80+ var req = hh . request ( importPath , function ( res ) {
81+ collect ( res , function ( err , data ) {
82+ if ( err ) return reject ( err ) ;
83+ resolve ( { index : index , data : data . toString ( ) } ) ;
84+ } ) ;
85+ } ) ;
86+ req . on ( "error" , reject ) ;
87+ req . end ( ) ;
88+ } ) ;
9789 }
98- fileReady ( state ) ;
99- }
90+ } ) ( index ) ;
10091 }
101- // No import statements .
102- if ( count === 0 ) {
103- fileReady ( { done : true } ) ;
92+ // Nothing to import .
93+ if ( promises . length === 0 ) {
94+ callback ( null , vinyl ) ;
10495 return ;
10596 }
10697 // Adding trailing piece.
107- fileArray [ fileArray . length ] = contents . slice ( lastPos ) ;
108-
109- // todo: optimize do not scan all contents.
110- function fileReady ( state ) {
111- //console.log("fileReady.state", state);
112- state = state || { } ;
113- if ( fileArray . length > 0 ) {
114- contents = fileArray . join ( "" ) ;
115- }
116- if ( ! state . done ) {
117- //console.log("chunk.isVinyl", chunk.isVinyl);
118- var nextChunk ;
119- if ( chunk . isVinyl ) {
120- chunk . vinyl . contents = new Buffer ( contents ) ;
121- chunk . vinyl . base = state . directory ;
122- nextChunk = chunk . vinyl ;
123- } else {
124- nextChunk = Chunk . create ( {
125- contents : contents ,
126- directory : state . directory
98+ file [ file . length ] = contents . slice ( lastpos ) ;
99+ // Waiting promises.
100+ Promise . all ( promises ) . then ( function ( results ) {
101+ for ( var i = 0 ; i < results . length ; i ++ ) {
102+ var item = results [ i ] ;
103+ // file[item.index] = item.data;
104+ var vfile = new gutil . File ( {
105+ path : item . importFile ,
106+ contents : new Buffer ( item . data )
107+ } ) ;
108+ ( function ( item ) {
109+ results [ i ] = pify ( fileContents ) ( vfile , null ) . then ( function ( vfile ) {
110+ return { index : item . index , data : vfile . contents . toString ( ) } ;
127111 } ) ;
128- }
129- //console.log("state", state);
130- fileContents ( nextChunk , null , callback ) ;
131- return ;
112+ } ) ( item ) ;
132113 }
133- //console.log("chunk.isVinyl", chunk.isVinyl);
134- if ( chunk . isVinyl ) {
135- contents = new gutil . File ( {
136- cwd : data . cwd ,
137- base : data . base ,
138- path : data . path ,
139- contents : new Buffer ( contents )
140- } ) ;
114+ return Promise . all ( results ) ;
115+ } )
116+ . then ( function ( results ) {
117+ for ( var i = 0 ; i < results . length ; i ++ ) {
118+ var index = results [ i ] . index ;
119+ file [ index ] = results [ i ] . data ;
141120 }
142- callback ( null , contents ) ;
143- }
144-
121+ vinyl . contents = new Buffer ( file . join ( "" ) ) ;
122+ callback ( null , vinyl ) ;
123+ } )
124+ . catch ( callback ) ;
145125 }
146126
147127 return through . obj ( fileContents ) ;
148- } ;
128+ } ;
129+
130+ function isMatch ( path , options ) {
131+ if ( ! options ) {
132+ return true ;
133+ }
134+ if ( ! path ) {
135+ return false ;
136+ }
137+ options = options || { } ;
138+ var result ;
139+ if ( options . filter instanceof RegExp ) {
140+ var filter = options . filter ;
141+ filter . lastIndex = 0 ;
142+ result = filter . test ( path ) ;
143+ }
144+ if ( options . matchPattern && ! isUrl ( path ) ) {
145+ var matchPattern = options . matchPattern ;
146+ result = minimatch ( path , matchPattern , options . matchOptions ) ;
147+ }
148+ if ( options . extensions ) {
149+ var extensions = options . extensions ;
150+ var fileExt = getExtension ( path ) ;
151+ for ( var k = 0 ; k < extensions . length ; k ++ ) {
152+ var extension = extensions [ k ] ;
153+ var isInverse = extension . charAt ( 0 ) === "!" ;
154+ if ( isInverse ) {
155+ extension = extension . slice ( 1 ) ;
156+ }
157+ if ( isInverse && fileExt === extension ) { // !sass , sass === css
158+ return false ;
159+ } else if ( ! isInverse && fileExt !== extension ) {
160+ return false ;
161+ }
162+ }
163+ }
164+ if ( typeof result === "undefined" ) {
165+ result = true ;
166+ }
167+ return result ;
168+ }
169+
170+ function isUrl ( s ) {
171+ var regexp = / ( h t t p | h t t p s ) : \/ \/ ( \w + : { 0 , 1 } \w * @ ) ? ( \S + ) ( : [ 0 - 9 ] + ) ? ( \/ | \/ ( [ \w # ! : . ? + = & % @ ! \- \/ ] ) ) ? / ;
172+ return regexp . test ( s ) ;
173+ }
174+
175+ function getExtension ( p ) {
176+ p = String ( p ) ;
177+ return p . substr ( p . lastIndexOf ( "." ) + 1 ) ;
178+ }
0 commit comments