gulp-shopify-sass
Advanced tools
Comparing version 0.3.1 to 0.3.2
219
index.js
'use strict'; | ||
var through = require('through2'); | ||
var path = require('path'); | ||
var gutil = require('gulp-util'); | ||
var PluginError = gutil.PluginError; | ||
var vfile = require('vinyl-file'); | ||
var vinyl = require('vinyl'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var gutil = require('gulp-util'); | ||
var through = require('through2'); | ||
var clonedeep = require('lodash.clonedeep'); | ||
const PLUGIN_NAME = 'gulp-shopify-sass'; | ||
// @param: dir full path and name | ||
// @return: boolean | ||
function checkFileExist (dir) { | ||
try { | ||
fs.accessSync(dir , fs.F_OK); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
/* | ||
* Most of the code in index.js are copied from gulp-sass | ||
*/ | ||
// @param: dir full path and name | ||
// @return: string | boolean | ||
function analyseDir (dir) { | ||
// possible extension array | ||
const dirReg = new RegExp(/(.+\/)(.+)$/, 'g'); | ||
const filenameReg = new RegExp(/^(\_)?(?:(.*(?=.scss))(.*)|(.*))$/, 'i'); | ||
////////////////////////////// | ||
// Main Gulp Shopify Sass function | ||
////////////////////////////// | ||
var gulpShopifySass = function gulpShopifySass (options, sync) { | ||
return through.obj(function (file, enc, cb) { | ||
// split whole path into path the filename | ||
let pathAndName = dirReg.exec(dir); | ||
var opts, contents; | ||
const filepath = pathAndName[1] || ''; | ||
let filename = pathAndName[2] || ''; | ||
if (file.isNull()) { | ||
return cb(null, file); | ||
} | ||
// [0] original filename | ||
// [1] '_' if exist in the filename, otherwise undefined | ||
// [2] filename if it has extension .scss or .scss.liquid, otherwise undefined | ||
// [3] file extension if filename has extionsion .scss or .scss.liquid, otherwise undefined | ||
// [4] filename if it doesn't have extension, otherwise undefined | ||
let filenameFrags = filenameReg.exec(filename); | ||
// do not support stream | ||
if(file.isStream()) { | ||
return cb(new gutil.PluginError(PLUGIN_NAME, 'Streaming not supported!')); | ||
} | ||
// move filename[4] to filename[2] if filename[2] is undefined | ||
filenameFrags[2] = filenameFrags[2] || filenameFrags[4]; | ||
////////////////////////////// | ||
// Handles returning the file to the stream | ||
////////////////////////////// | ||
var filePush = function filePush(contents) { | ||
// console.log(file); | ||
// console.log(file.contents); | ||
// console.log(contents); | ||
// file = new gutil.File({ | ||
// 'cwd': __dirname, | ||
// 'base': file.base, | ||
// 'path': gutil.replaceExtension(file.path, '.cat.scss.liquid'), | ||
// 'contents': contents | ||
// }); | ||
// remove original name, all index will reduce 1 | ||
filenameFrags.shift(); | ||
file.contents = new Buffer(contents); | ||
file.path = gutil.replaceExtension(file.path, '.cat.scss.liquid'); | ||
// remove filename[4] since it's been moved to [2] | ||
filenameFrags.pop() | ||
cb(null, file); | ||
}; | ||
// [0] was [1], [2] was [3] | ||
let prefix = filenameFrags[0] ? [filenameFrags[0]] : ['', '_']; | ||
let suffix = filenameFrags[2] ? [filenameFrags[2]] : ['.scss', '.scss.liquid']; | ||
let allCombinations = []; | ||
////////////////////////////// | ||
// Handles error message | ||
////////////////////////////// | ||
var errorM = function errorM(error) { | ||
var relativePath = '', | ||
filePath = error.file === 'stdin' ? file.path : error.file, | ||
message = ''; | ||
// check all possible combimations | ||
for (let i in prefix) { | ||
for (let j in suffix) { | ||
filenameFrags[0] = prefix[i]; | ||
filenameFrags[2] = suffix[j]; | ||
filename = filenameFrags.join(''); | ||
filePath = filePath ? filePath : file.path; | ||
relativePath = path.relative(process.cwd(), filePath); | ||
pathAndName = path.join(filepath, filename); | ||
message += gutil.colors.underline(relativePath) + '\n'; | ||
message += error.formatted; | ||
if (checkFileExist(pathAndName)) { | ||
return pathAndName; | ||
} | ||
} | ||
} | ||
error.messageFormatted = message; | ||
error.messageOriginal = error.message; | ||
// error.message = gutil.colors.stripColor(message); | ||
gutil.log('File to import: "' + dir + '" not found.'); | ||
error.relativePath = relativePath; | ||
return false; | ||
} | ||
return cb(new gutil.PluginError( | ||
PLUGIN_NAME, error | ||
)); | ||
}; | ||
// processing buffer | ||
if(file.isBuffer()) { | ||
////////////////////////////// | ||
// gulpShopifySass main process BEGIN | ||
////////////////////////////// | ||
function importReplacer (file) { | ||
opts = clonedeep(options || {}); | ||
opts.data = file.contents.toString(); | ||
var rex = /@import\s*(?:(?:'([^']+)')|(?:"([^"]+)"))\s*;/gi; | ||
var fileContents = file.contents.toString(); | ||
var fileDirname = path.dirname(file.path); | ||
var imports = {}; | ||
var match; | ||
// we set the file path here so that libsass can correctly resolve import paths | ||
opts.file = file.path; | ||
while(match = rex.exec(fileContents)) { | ||
// TODO: add includePaths feature in options and relavent processer | ||
// [1] single quotes | ||
// [2] double quotes | ||
var importFile = path.join(fileDirname, (match[1] || match[2])); | ||
// Ensure file's parent directory in the include path | ||
// if (opts.includePaths) { | ||
// if (typeof opts.includePaths === 'string') { | ||
// opts.includePaths = [opts.includePaths]; | ||
// } | ||
// } else { | ||
// opts.includePaths = []; | ||
// } | ||
const fileExistCheck = analyseDir(importFile); | ||
// opts.includePaths.unshift(path.dirname(file.path)); | ||
// if file exists, replace it | ||
if(fileExistCheck) { | ||
imports[match[0]] = fileExistCheck; | ||
} | ||
// TDDO: enable sync option once async render is done. Only support renderSync for now | ||
// if (sync === true) { | ||
////////////////////////////// | ||
// Sync Sass render | ||
////////////////////////////// | ||
} | ||
try { | ||
contents = gulpShopifySass.compiler.renderSync(opts); | ||
for(let imp in imports) { | ||
// replace @import with import file contents | ||
fileContents = fileContents.replace(new RegExp(imp, 'g'), importReplacer(vfile.readSync(imports[imp])).contents.toString()); | ||
} | ||
filePush(contents); | ||
} catch (error) { | ||
return errorM(error); | ||
} | ||
file.contents = new Buffer(fileContents); | ||
// } else { | ||
// ////////////////////////////// | ||
// // Async Sass render | ||
// ////////////////////////////// | ||
// var callback = function(error, catFile) { | ||
// if (error) { | ||
// return errorM(error); | ||
// } | ||
// filePush(catFile); | ||
// }; | ||
return file; | ||
// gulpShopifySass.compiler.render(opts, callback); | ||
// } | ||
////////////////////////////// | ||
// gulpShopifySass main process END | ||
////////////////////////////// | ||
} | ||
}); | ||
} | ||
module.exports = function () { | ||
return through.obj(function (file, enc, cb) { | ||
////////////////////////////// | ||
// Sync Shopify Sass render | ||
////////////////////////////// | ||
// do not support stream | ||
if(file.isStream()) { | ||
this.emit('error', new PluginError(PLUGIN_NAME, 'Streams are not supported!')); | ||
return cb(); | ||
} | ||
// TDDO: enable sync option once async render is done. Only support renderSync for now | ||
// processing buffer | ||
if(file.isBuffer()) { | ||
importReplacer(file); | ||
} | ||
// gulpShopifySass.sync = function sync(options) { | ||
// return gulpShopifySass(options, true); | ||
// }; | ||
this.push(file); | ||
////////////////////////////// | ||
// Log errors nicely | ||
////////////////////////////// | ||
gulpShopifySass.logError = function logError(error) { | ||
var message = new gutil.PluginError('sass', error.messageFormatted).toString(); | ||
process.stderr.write(message + '\n'); | ||
this.emit('end'); | ||
}; | ||
cb(); | ||
}); | ||
} | ||
////////////////////////////// | ||
// Store compiler in a prop | ||
////////////////////////////// | ||
gulpShopifySass.compiler = require('./lib/compiler'); | ||
module.exports = gulpShopifySass; |
{ | ||
"name": "gulp-shopify-sass", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"description": "Concatenate Sass files defined by the @import order", | ||
@@ -28,3 +28,6 @@ "main": "./index.js", | ||
"gulp": "^3.9.0", | ||
"lodash.clonedeep": "^4.5.0", | ||
"mocha": "^2.3.4", | ||
"pegjs": "^0.10.0", | ||
"pegjs-util": "^1.3.5", | ||
"should": "^8.1.1", | ||
@@ -31,0 +34,0 @@ "stream-array": "^1.1.1", |
@@ -17,20 +17,25 @@ # gulp-shopify-sass [![Build Status](https://travis-ci.org/theJian/gulp-shopify-sass.svg?branch=master)](https://travis-ci.org/theJian/gulp-shopify-sass) | ||
@import 'path-to-file/name'; | ||
@import 'path-to-file/_name'; | ||
@import 'path-to-file/name.scss'; | ||
@import 'path-to-file/_name.scss'; | ||
```javascript | ||
@import 'path-to-file/name'; | ||
@import 'path-to-file/_name'; | ||
@import 'path-to-file/name.scss'; | ||
@import 'path-to-file/_name.scss'; | ||
``` | ||
All of above will have the same result. | ||
```javascript | ||
'use strict'; | ||
var gulp = require('gulp'); | ||
var gss = require('gulp-shopify-sass'); | ||
var gulp = require('gulp'); | ||
var gss = require('gulp-shopify-sass'); | ||
gulp.task('default', function() { | ||
return gulp.src('./*.scss') | ||
.pipe(gss()); | ||
}); | ||
gulp.task('default', function() { | ||
return gulp.src('./*.scss') | ||
.pipe(gss()) | ||
.pipe(gulp.dest('./path/to/dist')); | ||
}); | ||
``` | ||
# License | ||
MIT license | ||
MIT license |
249
test/test.js
@@ -5,89 +5,204 @@ var assert = require('stream-assert'); | ||
var gulp = require('gulp'); | ||
var path = require('path'); | ||
var gutil = require('gulp-util'); | ||
var fs = require('fs'); | ||
var gulpShopifySass = require('../index'); | ||
var test = require('./test-stream'); | ||
describe('gulp-shopify-sass', function () { | ||
describe('in buffer mode', function () { | ||
var createVinyl = function createVinyl(filename, contents) { | ||
var base = path.join(__dirname, 'fixtures', 'scss'); | ||
var filePath = path.join(base, filename); | ||
return new gutil.File({ | ||
'cwd': __dirname, | ||
'base': base, | ||
'path': filePath, | ||
'contents': contents || fs.readFileSync(filePath) | ||
}); | ||
}; | ||
it('skip files doesn\'t exist', function (done) { | ||
test('@import "foo.scss";') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('@import "foo.scss";')})) | ||
.pipe(assert.end(done)); | ||
describe('gulp-shopify-sass', function() { | ||
it('skip files doesn\'t exist', function(done) { | ||
var stream = gulpShopifySass(); | ||
var emptyFile = { | ||
'isNull': function() { | ||
return true; | ||
} | ||
}; | ||
stream.on('data', function (data) { | ||
data.should.equal(emptyFile); | ||
done(); | ||
}); | ||
stream.write(emptyFile); | ||
}); | ||
it('work on single sass file', function (done) { | ||
test('.class-name{}') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name{}')})) | ||
.pipe(assert.end(done)); | ||
it('should emit error when file isStream()', function(done) { | ||
var stream = gulpShopifySass(); | ||
var streamFile = { | ||
'isNull': function() { | ||
return false; | ||
}, | ||
'isStream': function() { | ||
return true; | ||
} | ||
}; | ||
stream.on('error', function (err) { | ||
err.message.should.equal('Streaming not supported!'); | ||
done(); | ||
}); | ||
stream.write(streamFile); | ||
}); | ||
// it('replace import on single file', function (done) { | ||
// test('@import "file1.scss";', '.class-name{}') | ||
// .pipe(gulpShopifySass()) | ||
// .pipe(assert.length(2)) | ||
// .pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name{}')})) | ||
// .pipe(assert.end(done)); | ||
// }); | ||
it('should compile an empty sass file', function(done) { | ||
var sassFile = createVinyl('empty.scss'); | ||
var stream = gulpShopifySass(); | ||
// it('replace import recursively', function (done) { | ||
// test('@import "file1.scss";', '@import "file2.scss";', '.class-name{}') | ||
// .pipe(gulpShopifySass()) | ||
// .pipe(assert.length(3)) | ||
// .pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name{}')})) | ||
// .pipe(assert.end(done)); | ||
// }); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'empty.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal(''); | ||
done(); | ||
}); | ||
it('replace import', function (done) { | ||
gulp.src('./test/fixtures/b.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name {}')})) | ||
.pipe(assert.end(done)); | ||
stream.write(sassFile); | ||
}); | ||
it('replace import recursively', function (done) { | ||
gulp.src('./test/fixtures/c.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name {}')})) | ||
.pipe(assert.end(done)); | ||
it('work on single sass file', function(done) { | ||
var sassFile = createVinyl('_single.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), '_single.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'scss', '_single.scss'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
it('replace multiple import', function (done) { | ||
gulp.src('./test/fixtures/d.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name {}\n.class-name {}')})) | ||
.pipe(assert.end(done)); | ||
it('should replace import', function(done) { | ||
var sassFile = createVinyl('import.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'import.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'scss', '_single.scss'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
it('replace multiple types of import', function (done) { | ||
gulp.src('./test/fixtures/e.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name {}\n.class-name {}\n.class-name {}\n.class-name {}')})) | ||
.pipe(assert.end(done)); | ||
it('replace import recursively', function(done) { | ||
var sassFile = createVinyl('recursive.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'recursive.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'scss', '_single.scss'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
it('replace import .scss.liquid', function (done) { | ||
gulp.src('./test/fixtures/f.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.dash {}\n.dash {}\n.dash {}\n.dash {}')})) | ||
.pipe(assert.end(done)); | ||
it('replace multiple import', function(done) { | ||
var sassFile = createVinyl('multiple.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'multiple.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'expected', 'multiple.cat.scss.liquid'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
it('do not import .scss.liquid if .scss exist', function (done) { | ||
gulp.src('./test/fixtures/g.scss') | ||
.pipe(gulpShopifySass()) | ||
.pipe(assert.length(1)) | ||
.pipe(assert.first(function(f){f.contents.toString().should.equal('.class-name {}\n.class-name {}')})) | ||
.pipe(assert.end(done)); | ||
it('replace import with different name variations', function(done) { | ||
var sassFile = createVinyl('variations.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'variations.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'expected', 'variations.cat.scss.liquid'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
}); | ||
}); | ||
it('replace import .scss.liquid', function(done) { | ||
var sassFile = createVinyl('import.liquid.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'import.liquid.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'expected', 'import.liquid.cat.scss.liquid'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
it('do not import .scss.liquid if .scss exist', function(done) { | ||
var sassFile = createVinyl('extensionOverride.scss'); | ||
var stream = gulpShopifySass(); | ||
stream.on('data', function(catScssFile) { | ||
should.exist(catScssFile); | ||
should.exist(catScssFile.path); | ||
should.exist(catScssFile.relative); | ||
should.exist(catScssFile.contents); | ||
should.equal(path.basename(catScssFile.path), 'extensionOverride.cat.scss.liquid'); | ||
String(catScssFile.contents).should.equal( | ||
fs.readFileSync(path.join(__dirname, 'fixtures', 'expected', 'extentionOverride.cat.scss.liquid'), 'utf8') | ||
); | ||
done(); | ||
}); | ||
stream.write(sassFile); | ||
}); | ||
}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
22057
24
496
41
9
4
1