gulp-include
Advanced tools
Comparing version 2.3.0 to 2.3.1
# Changelog | ||
#### 2.3.1 | ||
* Isolated include to solve some scoping issues that happens when running multiple includes in parallel. | ||
#### 2.3.0 | ||
@@ -4,0 +7,0 @@ * The automatic throwing of errors caused discomfort for some, now simply warns by default, but added the possibility to turn on if necessary |
452
index.js
@@ -9,301 +9,297 @@ var fs = require('fs'), | ||
var SourceMapGenerator = require('source-map').SourceMapGenerator; | ||
var SourceMapConsumer = require('source-map').SourceMapConsumer; | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var extensions = null, // The extension to be searched after | ||
includedFiles = [], // Keeping track of what files have been included | ||
includePaths = false, // The paths to be searched | ||
hardFail = false; // Throw error when no match | ||
var SourceMapGenerator = require('source-map').SourceMapGenerator; | ||
var SourceMapConsumer = require('source-map').SourceMapConsumer; | ||
module.exports = function (params) { | ||
var params = params || {}; | ||
includedFiles = []; | ||
extensions = null; | ||
includePaths = false; | ||
hardFail = false; | ||
var extensions = null, // The extension to be searched after | ||
includedFiles = [], // Keeping track of what files have been included | ||
includePaths = false, // The paths to be searched | ||
hardFail = false; // Throw error when no match | ||
// Check for includepaths in the params | ||
if (params.includePaths) { | ||
if (typeof params.includePaths == "string") { | ||
// Arrayify the string | ||
includePaths = [params.includePaths]; | ||
}else if (Array.isArray(params.includePaths)) { | ||
// Set this array to the includepaths | ||
includePaths = params.includePaths; | ||
} | ||
// Check for includepaths in the params | ||
if (params.includePaths) { | ||
if (typeof params.includePaths == "string") { | ||
// Arrayify the string | ||
includePaths = [params.includePaths]; | ||
}else if (Array.isArray(params.includePaths)) { | ||
// Set this array to the includepaths | ||
includePaths = params.includePaths; | ||
} | ||
} | ||
// Toggle error reporting | ||
if (params.hardFail != undefined) { | ||
hardFail = params.hardFail; | ||
// Toggle error reporting | ||
if (params.hardFail != undefined) { | ||
hardFail = params.hardFail; | ||
} | ||
if (params.extensions) { | ||
extensions = typeof params.extensions === 'string' ? [params.extensions] : params.extensions; | ||
} | ||
function include(file, callback) { | ||
if (file.isNull()) { | ||
return callback(null, file); | ||
} | ||
if (params.extensions) { | ||
extensions = typeof params.extensions === 'string' ? [params.extensions] : params.extensions; | ||
if (file.isStream()) { | ||
throw new gutil.PluginError('gulp-include', 'stream not supported'); | ||
} | ||
function include(file, callback) { | ||
if (file.isNull()) { | ||
return callback(null, file); | ||
} | ||
if (file.isBuffer()) { | ||
var result = processInclude(String(file.contents), file.path, file.sourceMap); | ||
file.contents = new Buffer(result.content); | ||
if (file.isStream()) { | ||
throw new gutil.PluginError('gulp-include', 'stream not supported'); | ||
} | ||
if (file.sourceMap && result.map) { | ||
if (Object.prototype.toString.call(result.map) === '[object String]') { | ||
result.map = JSON.parse(result.map); | ||
} | ||
if (file.isBuffer()) { | ||
var result = processInclude(String(file.contents), file.path, file.sourceMap); | ||
file.contents = new Buffer(result.content); | ||
// relative-ize the paths in the map | ||
result.map.file = path.relative(file.base, result.map.file); | ||
result.map.sources.forEach(function (source, q) { | ||
result.map.sources[q] = path.relative(file.base, result.map.sources[q]); | ||
}); | ||
if (file.sourceMap && result.map) { | ||
if (Object.prototype.toString.call(result.map) === '[object String]') { | ||
result.map = JSON.parse(result.map); | ||
} | ||
// relative-ize the paths in the map | ||
result.map.file = path.relative(file.base, result.map.file); | ||
result.map.sources.forEach(function (source, q) { | ||
result.map.sources[q] = path.relative(file.base, result.map.sources[q]); | ||
}); | ||
applySourceMap(file, result.map); | ||
} | ||
applySourceMap(file, result.map); | ||
} | ||
callback(null, file); | ||
} | ||
return es.map(include) | ||
}; | ||
callback(null, file); | ||
} | ||
function processInclude(content, filePath, sourceMap) { | ||
var matches = content.match(/^(\s+)?(\/\/|\/\*|\#|\<\!\-\-)(\s+)?=(\s+)?(include|require)(.+$)/mg); | ||
var relativeBasePath = path.dirname(filePath); | ||
function processInclude(content, filePath, sourceMap) { | ||
var matches = content.match(/^(\s+)?(\/\/|\/\*|\#|\<\!\-\-)(\s+)?=(\s+)?(include|require)(.+$)/mg); | ||
var relativeBasePath = path.dirname(filePath); | ||
if (!matches) return {content: content, map: null}; | ||
if (!matches) return {content: content, map: null}; | ||
// Apply sourcemaps | ||
var map = null, mapSelf, lastMappedLine, currentPos, insertedLines; | ||
if (sourceMap) { | ||
map = new SourceMapGenerator({file: unixStylePath(filePath)}); | ||
lastMappedLine = 1; | ||
currentPos = 0; | ||
insertedLines = 0; | ||
// Apply sourcemaps | ||
var map = null, mapSelf, lastMappedLine, currentPos, insertedLines; | ||
if (sourceMap) { | ||
map = new SourceMapGenerator({file: unixStylePath(filePath)}); | ||
lastMappedLine = 1; | ||
currentPos = 0; | ||
insertedLines = 0; | ||
mapSelf = function (currentLine) { // maps current file between matches and after all matches | ||
var currentOrigLine = currentLine - insertedLines; | ||
mapSelf = function (currentLine) { // maps current file between matches and after all matches | ||
var currentOrigLine = currentLine - insertedLines; | ||
for (var q = (currentLine - lastMappedLine); q > 0; q--) { | ||
map.addMapping({ | ||
generated: { | ||
line: currentLine - q, | ||
column: 0 | ||
}, | ||
original: { | ||
line: currentOrigLine - q, | ||
column: 0 | ||
}, | ||
source: filePath | ||
}); | ||
} | ||
for (var q = (currentLine - lastMappedLine); q > 0; q--) { | ||
map.addMapping({ | ||
generated: { | ||
line: currentLine - q, | ||
column: 0 | ||
}, | ||
original: { | ||
line: currentOrigLine - q, | ||
column: 0 | ||
}, | ||
source: filePath | ||
}); | ||
} | ||
lastMappedLine = currentLine; | ||
}; | ||
} | ||
for (var i = 0; i < matches.length; i++) { | ||
var leadingWhitespaceMatch = matches[i].match(/^\s*/); | ||
var leadingWhitespace = null; | ||
if (leadingWhitespaceMatch) { | ||
leadingWhitespace = leadingWhitespaceMatch[0].replace("\n", ""); | ||
lastMappedLine = currentLine; | ||
}; | ||
} | ||
// Remove beginnings, endings and trim. | ||
var includeCommand = matches[i] | ||
.replace(/\s+/g, " ") | ||
.replace(/(\/\/|\/\*|\#|<!--)(\s+)?=(\s+)?/g, "") | ||
.replace(/(\*\/|-->)$/g, "") | ||
.replace(/['"]/g, "") | ||
.trim(); | ||
for (var i = 0; i < matches.length; i++) { | ||
var leadingWhitespaceMatch = matches[i].match(/^\s*/); | ||
var leadingWhitespace = null; | ||
if (leadingWhitespaceMatch) { | ||
leadingWhitespace = leadingWhitespaceMatch[0].replace("\n", ""); | ||
} | ||
var split = includeCommand.split(" "); | ||
// Remove beginnings, endings and trim. | ||
var includeCommand = matches[i] | ||
.replace(/\s+/g, " ") | ||
.replace(/(\/\/|\/\*|\#|<!--)(\s+)?=(\s+)?/g, "") | ||
.replace(/(\*\/|-->)$/g, "") | ||
.replace(/['"]/g, "") | ||
.trim(); | ||
var currentLine; | ||
if (sourceMap) { | ||
// get position of current match and get current line number | ||
currentPos = content.indexOf(matches[i], currentPos); | ||
currentLine = currentPos === -1 ? 0 : content.substr(0, currentPos).match(/^/mg).length; | ||
var split = includeCommand.split(" "); | ||
// sometimes the line matches the leading \n and sometimes it doesn't. wierd. | ||
// in case it does, increment the current line counter | ||
if (leadingWhitespaceMatch[0][0] == '\n') currentLine++; | ||
var currentLine; | ||
if (sourceMap) { | ||
// get position of current match and get current line number | ||
currentPos = content.indexOf(matches[i], currentPos); | ||
currentLine = currentPos === -1 ? 0 : content.substr(0, currentPos).match(/^/mg).length; | ||
mapSelf(currentLine); | ||
} | ||
// sometimes the line matches the leading \n and sometimes it doesn't. wierd. | ||
// in case it does, increment the current line counter | ||
if (leadingWhitespaceMatch[0][0] == '\n') currentLine++; | ||
// SEARCHING STARTS HERE | ||
// Split the directive and the path | ||
var includeType = split[0]; | ||
mapSelf(currentLine); | ||
} | ||
// Use glob for file searching | ||
var fileMatches = []; | ||
var includePath = ""; | ||
// SEARCHING STARTS HERE | ||
// Split the directive and the path | ||
var includeType = split[0]; | ||
if (includePaths != false) { | ||
// If includepaths are set, search in those folders | ||
for (var y = 0; y < includePaths.length; y++) { | ||
includePath = includePaths[y] + "/" + split[1]; | ||
// Use glob for file searching | ||
var fileMatches = []; | ||
var includePath = ""; | ||
if (includePaths != false) { | ||
// If includepaths are set, search in those folders | ||
for (var y = 0; y < includePaths.length; y++) { | ||
includePath = includePaths[y] + "/" + split[1]; | ||
var globResults = glob.sync(includePath, {mark: true}); | ||
fileMatches = fileMatches.concat(globResults); | ||
} | ||
}else{ | ||
// Otherwise search relatively | ||
includePath = relativeBasePath + "/" + split[1]; | ||
var globResults = glob.sync(includePath, {mark: true}); | ||
fileMatches = fileMatches.concat(globResults); | ||
fileMatches = globResults; | ||
} | ||
}else{ | ||
// Otherwise search relatively | ||
includePath = relativeBasePath + "/" + split[1]; | ||
var globResults = glob.sync(includePath, {mark: true}); | ||
fileMatches = globResults; | ||
} | ||
if (fileMatches.length < 1) fileNotFoundError(includePath); | ||
if (fileMatches.length < 1) fileNotFoundError(includePath); | ||
var replaceContent = ''; | ||
for (var y = 0; y < fileMatches.length; y++) { | ||
var globbedFilePath = fileMatches[y]; | ||
var replaceContent = ''; | ||
for (var y = 0; y < fileMatches.length; y++) { | ||
var globbedFilePath = fileMatches[y]; | ||
// If directive is of type "require" and file already included, skip to next. | ||
if (includeType == "require" && includedFiles.indexOf(globbedFilePath) > -1) continue; | ||
// If directive is of type "require" and file already included, skip to next. | ||
if (includeType == "require" && includedFiles.indexOf(globbedFilePath) > -1) continue; | ||
// If not in extensions, skip this file | ||
if (!inExtensions(globbedFilePath)) continue; | ||
// If not in extensions, skip this file | ||
if (!inExtensions(globbedFilePath)) continue; | ||
// Get file contents and apply recursive include on result | ||
// Unicode byte order marks are stripped from the start of included files | ||
var fileContents = stripBom(fs.readFileSync(globbedFilePath)); | ||
// Get file contents and apply recursive include on result | ||
// Unicode byte order marks are stripped from the start of included files | ||
var fileContents = stripBom(fs.readFileSync(globbedFilePath)); | ||
var result = processInclude(fileContents.toString(), globbedFilePath, sourceMap); | ||
var resultContent = result.content; | ||
var result = processInclude(fileContents.toString(), globbedFilePath, sourceMap); | ||
var resultContent = result.content; | ||
if (sourceMap) { | ||
var lines = resultContent.match(/^/mg).length; //count lines in result | ||
if (sourceMap) { | ||
var lines = resultContent.match(/^/mg).length; //count lines in result | ||
if (result.map) { // result had a map, merge mappings | ||
if (Object.prototype.toString.call(result.map) === '[object String]') { | ||
result.map = JSON.parse(result.map); | ||
} | ||
if (result.map) { // result had a map, merge mappings | ||
if (Object.prototype.toString.call(result.map) === '[object String]') { | ||
result.map = JSON.parse(result.map); | ||
} | ||
if (result.map.mappings && result.map.mappings.length > 0) { | ||
var resultMap = new SourceMapConsumer(result.map); | ||
resultMap.eachMapping(function (mapping) { | ||
if (!mapping.source) return; | ||
if (result.map.mappings && result.map.mappings.length > 0) { | ||
var resultMap = new SourceMapConsumer(result.map); | ||
resultMap.eachMapping(function (mapping) { | ||
if (!mapping.source) return; | ||
map.addMapping({ | ||
generated: { | ||
line: mapping.generatedLine + currentLine - 1, | ||
column: mapping.generatedColumn + (leadingWhitespace ? leadingWhitespace.length : 0) | ||
}, | ||
original: { | ||
line: mapping.originalLine, | ||
column: mapping.originalColumn | ||
}, | ||
source: mapping.source, | ||
name: mapping.name | ||
}); | ||
}); | ||
if (result.map.sourcesContent) { | ||
result.map.sourcesContent.forEach(function(sourceContent, i) { | ||
map.setSourceContent(result.map.sources[i], sourceContent); | ||
}); | ||
} | ||
} | ||
} else { // result was a simple file, map whole file to new location | ||
for (var q = 0; q < lines; q++) { | ||
map.addMapping({ | ||
generated: { | ||
line: mapping.generatedLine + currentLine - 1, | ||
column: mapping.generatedColumn + (leadingWhitespace ? leadingWhitespace.length : 0) | ||
line: currentLine + q, | ||
column: leadingWhitespace ? leadingWhitespace.length : 0 | ||
}, | ||
original: { | ||
line: mapping.originalLine, | ||
column: mapping.originalColumn | ||
line: q + 1, | ||
column: 0 | ||
}, | ||
source: mapping.source, | ||
name: mapping.name | ||
source: globbedFilePath | ||
}); | ||
}); | ||
} | ||
if (result.map.sourcesContent) { | ||
result.map.sourcesContent.forEach(function(sourceContent, i) { | ||
map.setSourceContent(result.map.sources[i], sourceContent); | ||
}); | ||
if (sourceMap.sourcesContent) { | ||
map.setSourceContent(globbedFilePath, resultContent); | ||
} | ||
} | ||
} else { // result was a simple file, map whole file to new location | ||
for (var q = 0; q < lines; q++) { | ||
map.addMapping({ | ||
generated: { | ||
line: currentLine + q, | ||
column: leadingWhitespace ? leadingWhitespace.length : 0 | ||
}, | ||
original: { | ||
line: q + 1, | ||
column: 0 | ||
}, | ||
source: globbedFilePath | ||
}); | ||
} | ||
if (sourceMap.sourcesContent) { | ||
map.setSourceContent(globbedFilePath, resultContent); | ||
} | ||
// increment/set map line counters | ||
insertedLines += lines; | ||
currentLine += lines; | ||
lastMappedLine = currentLine; | ||
} | ||
// increment/set map line counters | ||
insertedLines += lines; | ||
currentLine += lines; | ||
lastMappedLine = currentLine; | ||
} | ||
if (includedFiles.indexOf(globbedFilePath) == -1) includedFiles.push(globbedFilePath); | ||
if (includedFiles.indexOf(globbedFilePath) == -1) includedFiles.push(globbedFilePath); | ||
// If the last file did not have a line break, and it is not the last file in the matched glob, | ||
// add a line break to the end | ||
if (!resultContent.trim().match(/\n$/) && y != fileMatches.length-1) { | ||
resultContent += "\n"; | ||
} | ||
// If the last file did not have a line break, and it is not the last file in the matched glob, | ||
// add a line break to the end | ||
if (!resultContent.trim().match(/\n$/) && y != fileMatches.length-1) { | ||
resultContent += "\n"; | ||
if (leadingWhitespace) resultContent = addLeadingWhitespace(leadingWhitespace, resultContent); | ||
replaceContent += resultContent; | ||
} | ||
if (leadingWhitespace) resultContent = addLeadingWhitespace(leadingWhitespace, resultContent); | ||
// REPLACE | ||
if (replaceContent.length) { | ||
// sometimes the line matches the leading \n and sometimes it doesn't. wierd. | ||
// in case it does, preserve that leading \n | ||
if (leadingWhitespaceMatch[0][0] === '\n') { | ||
replaceContent = '\n' + replaceContent; | ||
} | ||
replaceContent += resultContent; | ||
content = content.replace(matches[i], function() { return replaceContent }); | ||
insertedLines--; // adjust because the original line with comment was removed | ||
} | ||
} | ||
// REPLACE | ||
if (replaceContent.length) { | ||
// sometimes the line matches the leading \n and sometimes it doesn't. wierd. | ||
// in case it does, preserve that leading \n | ||
if (leadingWhitespaceMatch[0][0] === '\n') { | ||
replaceContent = '\n' + replaceContent; | ||
} | ||
if (sourceMap) { | ||
currentLine = content.match(/^/mg).length + 1; | ||
content = content.replace(matches[i], function() { return replaceContent }); | ||
insertedLines--; // adjust because the original line with comment was removed | ||
mapSelf(currentLine); | ||
} | ||
return {content: content, map: map ? map.toString() : null}; | ||
} | ||
if (sourceMap) { | ||
currentLine = content.match(/^/mg).length + 1; | ||
function unixStylePath(filePath) { | ||
return filePath.replace(/\\/g, '/'); | ||
} | ||
mapSelf(currentLine); | ||
function addLeadingWhitespace(whitespace, string) { | ||
return string.split("\n").map(function(line) { | ||
return whitespace + line; | ||
}).join("\n"); | ||
} | ||
return {content: content, map: map ? map.toString() : null}; | ||
} | ||
function fileNotFoundError(includePath) { | ||
if (hardFail) { | ||
throw new gutil.PluginError('gulp-include', 'No files found matching ' + includePath); | ||
}else{ | ||
console.warn( | ||
gutil.colors.yellow('WARN: ') + | ||
gutil.colors.cyan('gulp-include') + | ||
' - no files found matching ' + includePath | ||
); | ||
} | ||
} | ||
function unixStylePath(filePath) { | ||
return filePath.replace(/\\/g, '/'); | ||
} | ||
function addLeadingWhitespace(whitespace, string) { | ||
return string.split("\n").map(function(line) { | ||
return whitespace + line; | ||
}).join("\n"); | ||
} | ||
function fileNotFoundError(includePath) { | ||
if (hardFail) { | ||
throw new gutil.PluginError('gulp-include', 'No files found matching ' + includePath); | ||
}else{ | ||
console.warn( | ||
gutil.colors.yellow('WARN: ') + | ||
gutil.colors.cyan('gulp-include') + | ||
' - no files found matching ' + includePath | ||
); | ||
function inExtensions(filePath) { | ||
if (!extensions) return true; | ||
for (var i = 0; i < extensions.length; i++) { | ||
var re = extensions[i] + "$"; | ||
if (filePath.match(re)) return true; | ||
} | ||
return false; | ||
} | ||
} | ||
function inExtensions(filePath) { | ||
if (!extensions) return true; | ||
for (var i = 0; i < extensions.length; i++) { | ||
var re = extensions[i] + "$"; | ||
if (filePath.match(re)) return true; | ||
} | ||
return false; | ||
} | ||
return es.map(include) | ||
}; |
{ | ||
"name": "gulp-include", | ||
"version": "2.3.0", | ||
"version": "2.3.1", | ||
"description": "Makes inclusion of files a breeze. Enables functionality similar to that of snockets / sprockets or other file insertion compilation tools.", | ||
@@ -5,0 +5,0 @@ "homepage": "http://github.com/wiledal/gulp-include", |
29761
550