UNPKG

fis-parser-sass

Version:

A parser plugin for fis to compile sass file.

244 lines (185 loc) 6.21 kB
/** * 接管sass的@import内嵌, 主要用来解决 编译缓存依赖问题。 */ var map = (function() { return { reg: /\/\*embed:(.*?)\*\//ig, wrap: function( value ) { return '/*embed:' + value + '*/'; } }; })(); var sass = require('fis-sass'); var stack = {}; var required; function fixLineBreak( content ) { return content.replace(/\r\n|\r|\n/g, '\n'); } function isEmpty(obj) { if (obj) { for (var key in obj) { return false; } } return true; } // 匹配scss内嵌代码:@import 'xxx'; // @import 'xxx', 'xxx'; function _process( content ) { var reg = /((?:\/\/.*?\n)|(?:\/\*[\s\S]*?\*\/))|(?:@import\s([\s\S]*?)(?:\n|$)(?!\s+[^{@]*\n))/ig; // var reg = /@import[\s\S]*?;/ig; var rUrl = /^url/i; var rEnd = /;$/; content = fixLineBreak( content ); return content.replace( reg, function( all, comments, value ) { var files; value = value ? value.trim().replace( rEnd, '' ) : ''; // If it's comments or If the @import has any media queries. if ( comments || /('|").*?\1\s+[^'"]+$/.exec(value) ) { return all; } files = value.split(/\s*,?\s+/m).map(function( value ) { var quote = '', match; value = value.trim(); match = /^('|")(.*)\1$/.exec( value ); if ( match ) { value = match[ 2 ]; quote = match[ 1 ]; } // If the file’s extension is .css. if ( /\.css$/i.exec( value ) || // If the filename begins with http://. /^http/i.exec( value ) || // If the filename is a url(). /^url/i.exec( value ) ) { return '@import ' + quote + value + quote + ';'; } return map.wrap( value ); }); return files.join('\n'); }); } // 查找文件。 function lookup( name, ext, paths ) { var files = [], filename = name, basename = filename, dirname = '', mapping, i, j, len, len2, path, info; files.push( filename ); if ( /^(.*(?:\/|\\))([^\/\\]*?)$/.exec( filename ) ) { dirname = RegExp.$1; basename = RegExp.$2; } // 自动加后缀。 if ( !/\.(scss|sass)$/.exec( basename ) ) { filename = dirname + basename + ext; files.push( filename ); if ( !/^_/.exec( basename ) ) { filename = dirname + '_' + basename + ext; files.push( filename ); } mapping = { '.sass': '.scss', '.scss': '.sass' }; if ( mapping[ ext ] ) { filename = dirname + basename + mapping[ ext ]; files.push( filename ); if ( !/^_/.exec( basename ) ) { filename = dirname + '_' + basename + mapping[ ext ]; files.push( filename ); } } } len = files.length; len2 = paths.length; for ( i = 0; i < len; i++ ) { name = files[ i ]; for ( j = 0; j < len2; j++ ) { info = fis.uri( name, paths[ j ] ); if( info.file && info.file.isFile() ) { return info.file; } } } // console.log( paths, files ); } function isSassSyntax( content, file ) { return file.ext === '.sass'/* && !~content.indexOf('{')*/; } function unique( arr ) { return arr.filter(function( item, index, arr ) { return arr.indexOf( item ) === index; }); } var compile = module.exports = function( content, file, opts ) { if ( isSassSyntax( content, file ) ) { content = sass.sass2scss( content ); } required = {}; opts.data = before( content, file, unique( opts.includePaths ) ); try { content = sass.renderSync( opts ); } catch (ex) { fis.log.error(ex); } content = after( content, file, opts.includePaths ); return content; }; var before = compile.before = function( content, currentFile, paths) { // @todo use cache of this progress. var ext = currentFile.ext; paths = unique( paths ); return _process( content ).replace( map.reg, function( all, value ) { var file = lookup( value, ext, paths ), content; if ( file ) { // 已经在堆里面了 if ( stack[ file.realpath ] ) { fis.log.error( 'can\'t embed file ' + file.basename + '.' ); } // 如果已经引入过了,就不再引入。 // 类似与include_once. if ( required[ file.realpath ] ) { return ''; } // 有可能当前文件并没有经过 fis 的compile,以至于没有 cahce 对象。 if (currentFile.cache) { currentFile.cache.addDeps(file.realpath); } stack[ file.realpath ] = true; required[ file.realpath ] = true; content = file.getContent(); if ( isSassSyntax( content, file ) ) { content = sass.sass2scss( content ); } content = before( content, file, [ file.dirname ].concat( paths ) ); content = fixPath(content, file); delete stack[ file.realpath ]; return content; } else { fis.log.error( value + ' not found!' ); return ''; } }); }; var after = compile.after = function( content, file, paths ) { return content; }; var fixPath = compile.fixPath = function(content, file) { // 处理,解决资源引用路径问题。 content = fis.compile.extCss(content); return content.replace(fis.compile.lang.reg, function(all, type, value) { var info = fis.uri(value, file.dirname); if (info.file) { value = info.quote + info.file.subpath + info.query + info.quote; } if (type === 'embed' || type === 'jsEmbed') { value = fis.compile.lang[type].ld + value + fis.compile.lang[type].rd; } return value; }); }