gulp-include-inline
Advanced tools
Comparing version 0.1.0 to 0.1.1
263
lib/index.js
@@ -14,164 +14,169 @@ 'use strict'; | ||
module.exports = function(opts) { | ||
if (typeof opts === 'string') { | ||
opts = {prefix: opts}; | ||
} | ||
module.exports = function (opts) { | ||
if (typeof opts === 'string') { | ||
opts = { prefix: opts }; | ||
} | ||
opts = extend({}, { | ||
basepath: '@file', | ||
prefix: '@@', | ||
suffix: '', | ||
context: {}, | ||
filters: false, | ||
indent: false | ||
}, opts); | ||
opts = extend({}, { | ||
basepath: '@file', | ||
prefix: '@@', | ||
suffix: '', | ||
context: {}, | ||
filters: false, | ||
indent: false | ||
}, opts); | ||
if (opts.basepath !== '@file') { | ||
opts.basepath = opts.basepath === '@root' ? process.cwd() : path.resolve(opts.basepath); | ||
} | ||
if (opts.basepath !== '@file') { | ||
opts.basepath = opts.basepath === '@root' ? process.cwd() : path.resolve(opts.basepath); | ||
} | ||
function fileInclude(file, enc, cb) { | ||
if (file.isNull()) { | ||
cb(null, file); | ||
} else if (file.isStream()) { | ||
file.contents.pipe(concat(function(data) { | ||
try { | ||
data = include(file, String(data)); | ||
cb(null, data); | ||
} catch (e) { | ||
cb(new gutil.PluginError('gulp-file-include', e.message)); | ||
function fileInclude(file, enc, cb) { | ||
if (file.isNull()) { | ||
cb(null, file); | ||
} else if (file.isStream()) { | ||
file.contents.pipe(concat(function (data) { | ||
try { | ||
data = include(file, String(data)); | ||
cb(null, data); | ||
} catch (e) { | ||
cb(new gutil.PluginError('gulp-file-include', e.message)); | ||
} | ||
})); | ||
} else if (file.isBuffer()) { | ||
try { | ||
file = include(file, String(file.contents)); | ||
cb(null, file); | ||
} catch (e) { | ||
cb(new gutil.PluginError('gulp-file-include', e.message)); | ||
} | ||
} | ||
})); | ||
} else if (file.isBuffer()) { | ||
try { | ||
file = include(file, String(file.contents)); | ||
cb(null, file); | ||
} catch (e) { | ||
cb(new gutil.PluginError('gulp-file-include', e.message)); | ||
} | ||
} | ||
} | ||
return through.obj(fileInclude); | ||
return through.obj(fileInclude); | ||
/** | ||
* utils | ||
*/ | ||
function stripCommentedIncludes(content, opts) { | ||
// remove single line html comments that use the format: <!-- @@include() --> | ||
var regex = new RegExp('<\!--(.*)' + opts.prefix + '[ ]*include([\\s\\S]*?)[ ]*' + opts.suffix + '-->', 'g'); | ||
return content.replace(regex, ''); | ||
} | ||
/** | ||
* utils | ||
*/ | ||
function stripCommentedIncludes(content, opts) { | ||
// remove single line html comments that use the format: <!-- @@include() --> | ||
var regex = new RegExp('<\!--(.*)' + opts.prefix + '[ ]*include([\\s\\S]*?)[ ]*' + opts.suffix + '-->', 'g'); | ||
return content.replace(regex, ''); | ||
} | ||
function include(file, text, data) { | ||
var filebase = opts.basepath === '@file' ? path.dirname(file.path) : opts.basepath; | ||
var currentFilename = path.resolve(file.base, file.path); | ||
function include(file, text, data) { | ||
var filebase = opts.basepath === '@file' ? path.dirname(file.path) : opts.basepath; | ||
var currentFilename = path.resolve(file.base, file.path); | ||
data = extend(true, {}, opts.context, data || {}); | ||
data.content = text; | ||
data = extend(true, {}, opts.context, data || {}); | ||
data.content = text; | ||
text = stripCommentedIncludes(text, opts); | ||
text = replaceOperator(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'if', | ||
handler: conditionalHandler | ||
}); | ||
text = replaceOperator(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'for', | ||
handler: forHandler | ||
}); | ||
text = replaceVariable(text, data, opts); | ||
text = replaceFunction(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'include', | ||
handler: includeHandler | ||
}); | ||
text = stripCommentedIncludes(text, opts); | ||
text = replaceOperator(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'if', | ||
handler: conditionalHandler | ||
}); | ||
text = replaceOperator(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'for', | ||
handler: forHandler | ||
}); | ||
text = replaceVariable(text, data, opts); | ||
text = replaceFunction(text, { | ||
prefix: opts.prefix, | ||
suffix: opts.suffix, | ||
name: 'include', | ||
handler: includeHandler | ||
}); | ||
function conditionalHandler(inst) { | ||
// jshint ignore: start | ||
var condition = new Function('var context = this; with (context) { return ' + inst.args + '; }').call(data); | ||
// jshint ignore: end | ||
function conditionalHandler(inst) { | ||
// jshint ignore: start | ||
var condition = new Function('var context = this; with (context) { return ' + inst.args + '; }').call(data); | ||
// jshint ignore: end | ||
return condition ? inst.body : ''; | ||
} | ||
return condition ? inst.body : ''; | ||
} | ||
function forHandler(inst) { | ||
var condition = 'var context = this; with (context) { var result=""; for' + inst.args + ' { result+=`' + inst.body + '`; } return result; }'; | ||
// jshint ignore: start | ||
var result = new Function(condition).call(data); | ||
// jshint ignore: end | ||
function forHandler(inst) { | ||
var condition = 'var context = this; with (context) { var result=""; for' + inst.args + ' { result+=`' + inst.body + '`; } return result; }'; | ||
// jshint ignore: start | ||
var result = new Function(condition).call(data); | ||
// jshint ignore: end | ||
return result; | ||
} | ||
return result; | ||
} | ||
function includeHandler(inst) { | ||
var args = /[^)"\']*["\']([^"\']*)["\'](,\s*({[\s\S]*})){0,1}\s*/.exec(inst.args); | ||
function includeHandler(inst) { | ||
var args = /[^)"\']*["\']([^"\']*)["\'](,\s*({[\s\S]*})){0,1}\s*/.exec(inst.args); | ||
if (args) { | ||
var includePath = path.resolve(filebase, args[1]); | ||
// for checking if we are not including the current file again | ||
if (currentFilename.toLowerCase() === includePath.toLowerCase()) { | ||
throw new Error('recursion detected in file: ' + currentFilename); | ||
} | ||
if (args) { | ||
var includePath = path.resolve(filebase, args[1]); | ||
// for checking if we are not including the current file again | ||
if (currentFilename.toLowerCase() === includePath.toLowerCase()) { | ||
throw new Error('recursion detected in file: ' + currentFilename); | ||
} | ||
var includeContent = fs.readFileSync(includePath, 'utf-8'); | ||
var includeContent = fs.readFileSync(includePath, 'utf-8'); | ||
if (opts.indent) { | ||
includeContent = setIndent(inst.before, inst.before.length, includeContent); | ||
} | ||
if (opts.indent) { | ||
includeContent = setIndent(inst.before, inst.before.length, includeContent); | ||
} | ||
// need to double each `$` to escape it in the `replace` function | ||
// includeContent = includeContent.replace(/\$/gi, '$$$$'); | ||
// need to double each `$` to escape it in the `replace` function | ||
// includeContent = includeContent.replace(/\$/gi, '$$$$'); | ||
// apply filters on include content | ||
if (typeof opts.filters === 'object') { | ||
includeContent = applyFilters(includeContent, args.input); | ||
} | ||
// apply filters on include content | ||
if (typeof opts.filters === 'object') { | ||
includeContent = applyFilters(includeContent, args.input); | ||
} | ||
var recFile = new gutil.File({ | ||
cwd: process.cwd(), | ||
base: file.base, | ||
path: includePath, | ||
contents: new Buffer(includeContent) | ||
}); | ||
var recFile = new gutil.File({ | ||
cwd: process.cwd(), | ||
base: file.base, | ||
path: includePath, | ||
contents: new Buffer(includeContent) | ||
}); | ||
recFile = include(recFile, includeContent, args[3] ? JSON.parse(args[3]) : {}); | ||
recFile = include(recFile, includeContent, args[3] ? JSON.parse(args[3]) : {}); | ||
return String(recFile.contents); | ||
return String(recFile.contents); | ||
} | ||
} | ||
} | ||
file.contents = new Buffer(text); | ||
file.contents = new Buffer(text); | ||
return file; | ||
} | ||
function applyFilters(includeContent, match) { | ||
if (!match.match(/\)+$/)) { | ||
// nothing to filter return unchanged | ||
return includeContent; | ||
return file; | ||
} | ||
// now get the ordered list of filters | ||
var filterlist = match.split('(').slice(0, -1); | ||
filterlist = filterlist.map(function(str) { | ||
return opts.filters[str.trim()]; | ||
}); | ||
function applyFilters(includeContent, match) { | ||
if (!match.match(/\)+$/)) { | ||
// nothing to filter return unchanged | ||
return includeContent; | ||
} | ||
// compose them together into one function | ||
var filter = filterlist.reduce(compose); | ||
// now get the ordered list of filters, support only one filter once | ||
var filterlist = match.split('(').slice(0, -1); | ||
// and apply the composed function to the stringified content | ||
return filter(String(includeContent)); | ||
} | ||
var filterParameters = match.split(',').slice(1).map(function (item, index) { | ||
return item.match(/[\"\']([\s\S]*?)[\"\']/)[1]; | ||
}); | ||
filterlist = filterlist.map(function (str) { | ||
return opts.filters[str.trim()]; | ||
}); | ||
// compose them together into one function | ||
var filter = filterlist.reduce(compose); | ||
// and apply the composed function to the stringified content | ||
return filter.apply(this, [String(includeContent)].concat(filterParameters)); | ||
} | ||
}; | ||
function compose(f, g) { | ||
return function(x) { | ||
return f(g(x)); | ||
}; | ||
return function (x) { | ||
return f(g(x)); | ||
}; | ||
} |
{ | ||
"name": "gulp-include-inline", | ||
"version": "0.1.0", | ||
"version": "0.1.1", | ||
"description": "a gulp plugin for file include", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
10457
256