Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gulp-include

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gulp-include - npm Package Compare versions

Comparing version 1.1.1 to 2.0.0

test/expected/js/basic-include.js

260

index.js

@@ -7,32 +7,29 @@ var fs = require('fs'),

var extensions = null,
includedFiles = [];
var DIRECTIVE_REGEX = /^[\/\s#]*?=\s*?((?:require|include)(?:_tree|_directory)?)\s+(.*$)/mg;
var requiredFiles = {},
extensions = [];
module.exports = function (params) {
var params = params || {};
requiredFiles = {};
extensions = [];
includedFiles = [];
extensions = null;
if (params.extensions) {
extensions = typeof params.extensions === 'string' ? [params.extensions] : params.extensions;
extensions = typeof params.extensions === 'string' ? [params.extensions] : params.extensions;
}
function include(file, callback) {
if (file.isNull()) {
return callback(null, file);
}
if (file.isNull()) {
return callback(null, file);
}
if (file.isStream()) {
throw new gutil.PluginError('gulp-include', 'stream not supported');
}
if (file.isStream()) {
throw new gutil.PluginError('gulp-include', 'stream not supported');
}
if (file.isBuffer()) {
var newText = expand(String(file.contents), file.path);
file.contents = new Buffer(newText);
}
if (file.isBuffer()) {
var newText = processInclude(String(file.contents), file.path);
file.contents = new Buffer(newText);
}
callback(null, file);
callback(null, file);
}

@@ -43,170 +40,73 @@

function expand(fileContents, filePath) {
var regexMatch,
matches = [],
returnText = fileContents,
i, j;
DIRECTIVE_REGEX.lastIndex = 0;
while (regexMatch = DIRECTIVE_REGEX.exec(fileContents)) {
matches.push(regexMatch);
function processInclude(content, filePath) {
var matches = content.match(/^(\s+)?(\/\/|\/\*|\#)(\s+)?=(\s+)?(include|require)(.+$)/mg);
var relativeBasePath = path.dirname(filePath);
if (!matches) return content;
for (var i = 0; i < matches.length; i++) {
var leadingWhitespaceMatch = matches[i].match(/^(\s+)/);
var leadingWhitespace = null;
if (leadingWhitespaceMatch) leadingWhitespace = leadingWhitespaceMatch[0].replace("\n", "");
// Remove beginnings, endings and trim.
var includeCommand = matches[i]
.replace(/(\s+)/gi, " ")
.replace(/(\/\/|\/\*)(\s+)?=(\s+)?/g, "")
.replace(/(\*\/)$/gi, "")
.replace(/['"]/g, "")
.trim();
var split = includeCommand.split(" ");
// Split the directive and the path
var includeType = split[0];
var includePath = relativeBasePath + "/" + split[1];
// Use glob for file searching
var fileMatches = glob.sync(includePath, {mark: true});
var replaceContent = null;
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 not in extensions, skip this file
if (!inExtensions(globbedFilePath)) continue;
// Get file contents and apply recursive include on result
var fileContents = fs.readFileSync(globbedFilePath);
if (!replaceContent) replaceContent = "";
if (leadingWhitespace) fileContents = addLeadingWhitespace(leadingWhitespace, fileContents.toString());
replaceContent += processInclude(fileContents.toString(), 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 (!replaceContent.trim().match(/\n$/) && y != fileMatches.length-1) replaceContent += "\n";
}
i = matches.length;
while (i--) {
var match = matches[i],
original = match[0],
directiveType = match[1],
start = match.index,
end = start + original.length,
thisMatchText = "",
newMatchText = "",
files = globMatch(match, filePath),
fileName = "",
whitespace = null;
if (directiveType.indexOf("_tree") !== -1 || directiveType.indexOf("_directory") !== -1) {
thisMatchText += original + "\n";
}
for (j = 0; j < files.length; j++) {
fileName = files[j];
newMatchText = expand(String(fs.readFileSync(fileName)), fileName);
//Try to retain the same indent level from the original include line
whitespace = original.match(/^\s+/);
if (whitespace) {
//Discard newlines
whitespace = whitespace[0].replace("\n", "");
//Is there some whitespace left?
if (whitespace) {
newMatchText = addLeadingWhitespace(whitespace, newMatchText);
}
}
thisMatchText += newMatchText + "\n";
if (directiveType.indexOf('require') !== -1 || directiveType.indexOf('include') !== -1) {
requiredFiles[fileName] = true;
}
}
thisMatchText = thisMatchText || original;
returnText = replaceStringByIndices(returnText, start, end, thisMatchText);
// REPLACE
if (replaceContent) {
content = content.replace(matches[i], replaceContent);
}
return returnText ? returnText : fileContents;
}
return content;
}
function globMatch(match, filePath) {
var directiveType = match[1],
relativeFilePath = match[2],
files = [],
globs = [],
negations = [];
if (directiveType.indexOf('_tree') !== -1) {
relativeFilePath = relativeFilePath.concat('/**/*');
directiveType = directiveType.replace('_tree', '');
}
if (directiveType.indexOf('_directory') !== -1) {
relativeFilePath = relativeFilePath.concat('/*');
directiveType = directiveType.replace('_directory', '');
}
if (directiveType === 'require' || directiveType === 'include') {
if (relativeFilePath.charAt(0) === '[') {
relativeFilePath = eval(relativeFilePath);
for (var i = 0; i < relativeFilePath.length; i++) {
if (relativeFilePath[i].charAt(0) === '!') {
negations.push(relativeFilePath[i].slice(1))
} else {
globs.push(relativeFilePath[i]);
}
}
} else {
globs.push(relativeFilePath);
}
for (var i = 0; i < globs.length; i++) {
var globFiles = _internalGlob(globs[i], filePath);
files = union(files, globFiles);
}
for (var i = 0; i < negations.length; i++) {
var negationFiles = _internalGlob(negations[i], filePath);
files = difference(files, negationFiles);
}
}
return files;
}
function _internalGlob(thisGlob, filePath) {
var folderPath = path.dirname(filePath),
fullPath = path.join(folderPath, thisGlob.replace(/['"]/g, '')),
files;
files = glob.sync(fullPath, {
mark: true
});
files = files.filter(function (fileName) {
var slashSplit = fileName.split(/[\\\/]/),
thisExtension = fileName.split('.').pop();
//Ignore directories
if (slashSplit.pop() === '')
return false;
//Check for allowable extensions if specified, otherwise allow all extensions
if (extensions.length > 0 && extensions.indexOf(thisExtension) === -1) {
return false;
}
return true;
});
return files;
}
function replaceStringByIndices(string, start, end, replacement) {
return string.substring(0, start) + replacement + string.substring(end);
}
function addLeadingWhitespace(whitespace, string) {
return string.split("\n").map(function(line) {
return whitespace + line;
}).join("\n");
return string.split("\n").map(function(line) {
return whitespace + line;
}).join("\n");
}
//We can't use lo-dash's union function because it wouldn't support this: ["*.js", "app.js"], which requires app.js to come last
function union(arr1, arr2) {
if (arr1.length == 0) {
return arr2;
}
var index;
for (var i = 0; i < arr2.length; i++) {
if ((index = arr1.indexOf(arr2[i])) !== -1) {
arr1.splice(index, 1);
}
}
return arr1.concat(arr2);
}
function difference(arr1, arr2) {
var index;
for (var i = 0; i < arr2.length; i++) {
while ((index = arr1.indexOf(arr2[i])) !== -1) {
arr1.splice(index, 1);
}
}
return arr1;
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;
}
{
"name": "gulp-include",
"version": "1.1.1",
"version": "2.0.0",
"description": "Makes inclusion of files a breeze. Enables functionality similar to that of snockets / sprockets or other file insertion compilation tools.",

@@ -28,5 +28,5 @@ "homepage": "http://github.com/wiledal/gulp-include",

"event-stream": "~3.1.0",
"glob": "^4.0.0",
"glob": "^5.0.12",
"gulp-util": "~2.2.10"
}
}

@@ -7,93 +7,72 @@ #gulp-include [![NPM version][npm-image]][npm-url] ![Travis build][travis-image]

## Features
* Concatenate files with full control
* Respects indentation whitespace
* Uses [globs](https://www.npmjs.com/package/glob) for simple path control
* Works recursively (files can include files that can include files, and so on)
## Usage
First, install `gulp-include` as a dev dependency:
`npm install --save-dev gulp-include`
*Warning: if you are updating from 1.x.x to 2.x.x, please read this readme to get up to date on the behavior of `gulp-include`*
Then, add your _include-comments_ to your file.
_People who have experience with `sprockets` or `snockets` will feel at home._
An _include-comment_ looks like this:
```javascript
//= include relative/path/to/file.js
## Installation
```shell
npm install gulp-include
```
or if you want to get crazy, a glob pattern like so:
## Usage
Example `gulpfile.js`:
```javascript
//= include relative/path/to/directory/*.js
```
var gulp = require("gulp"),
include = require("gulp-include");
or to get even crazier, an array glob similar to commonly used in GruntJS:
```javascript
//= include ['app/someFramework.js', 'app/**/*.js', '!app/vendor/**/*', 'app/someLibrary.js']
```
gulp.task("scripts", function() {
console.log("-- gulp is running task 'scripts'");
(Note: for those of you unfamiliar with the above syntax, check out https://github.com/isaacs/node-glob
or http://gruntjs.com/configuring-tasks#globbing-patterns)
gulp.src("src/js/main.js")
.pipe(include())
.on('error', console.log)
.pipe(gulp.dest("dist/js"));
});
You can do all of this in any language, the only requirement is that the first character
on the line after any #, /, or white space characters is an equal sign.
```coffeescript
#= require_tree relative/path/to/directory
gulp.task("default", ["scripts"]);
```
`gulp-include` disregards whitespace, as long as the comment-line starts with a _newline_ followed `=` and contains `include`, `require` or `include_tree`, `require_tree`.
This plugin recursively expand files it includes, so you can nest includes inside of files that
were themselves included. IE:
## Options
* `extensions` (optional)
* Takes a `String` or an `Array` of extensions, eg: `"js"` or `["js", "coffee"]`
* If set, all directives that does not match the extension(s) will be ignored
`main.js`:
## Include directives
`gulp-include` uses directives similar to `sprockets` or `snockets`. A _directive_ is a comment in your files that `gulp-include` recognizes as a command.
Example directives:
```javascript
//=require vendor/jquery.js
//=require vendor/**/*.js
//=include relative/path/to/file.js
```
//= include included_file.js
```css
/*=include relative/path/to/file.css */
```
`included_file.js`:
```coffee
#=include relative/path/to/file.coffee
```
//= include recursive_include.js
```
And so on recursively to an arbitrary depth.
The example below compiles a several coffee-files and js-files into a single js-file:
`app.coffee`:
```coffeescript
`
//= require vendor/jquery.js
//= require vendor/modernizr.js
`
#= require controllers/AppController.coffee
#= require_tree views
class Main extends AppController
constructor: ->
console.log "This is main!"
window.main = new Main()
```
*Note:* The example above uses backticks (\`) to allow `gulp-coffee` to compile inline javascript
`gulpfile.js`:
The contents of the referenced file will replace the file.
### `require` vs. `include`
A file that is included with `require` will only be included if it has not been included before. Files included with `include` will _always_ be included.
For instance, let's say you want to include `jquery.js` only once, and before any of your other scripts in the same folder.
```javascript
var gulp = require('gulp'),
include = require('gulp-include'),
coffee = require('gulp-coffee');
gulp.task("scripts", function() {
gulp.src('src/js/app.coffee')
.pipe( include() )
.pipe( coffee() )
.pipe( gulp.dest("dist/js") )
});
gulp.task("default", "scripts");
//=require vendor/jquery.js
//=require vendor/*.js
```
Note: This also works recursively. If for instance, for the example above, if another file in the folder `vendor` is also including `jquery.js` with the `require`-directive it will be ignored.
## Options
* `extensions` (optional)
* Takes a `String` or an `Array` of extensions, eg: `"js"` or `["js", "coffee"]`
* If set, all inclusions that does not match the extension(s) will be ignored
## Release log
#### 2.0.0
* Core rewritten to be slimmer and more comprehensive.
* `require` and `include` no longer work the same. `require` will only include a file that hasn't been included yet. See readme for details.
* Tests have been rewritten based on the old ones, but also to fit the new functionality
* Deprecated `require_tree` and `require_directory` as they serve little purpose. Use globs (`path/to/**/*.xxx`) instead.
* Fixed spacing issues and
## Release log
#### 1.1.1

@@ -100,0 +79,0 @@ * Merged community fix by [trolev](https://github.com/trolev)

@@ -5,3 +5,3 @@ var gutil = require("gulp-util"),

fs = require("fs"),
vm = require('vm');
vm = require("vm");

@@ -11,253 +11,113 @@

describe("gulp-include", function () {
describe("File including", function () {
it("should replace special comments with file contents", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/basic-include.js",
contents: fs.readFileSync("test/fixtures/js/basic-include.js")
});
describe("directive matching", function () {
// Load the module indirectly, so that we can access
// the DIRECTIVE_REGEX
exports = {};
include_module = {
require: require,
console: console,
exports: exports,
module: {
exports: exports
}
}
vm.runInNewContext(fs.readFileSync('index.js'), include_module)
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
beforeEach(function (done) {
include_module.DIRECTIVE_REGEX.lastIndex = 0
done()
})
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/basic-include.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should keep whitespace when including", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/whitespace.js",
contents: fs.readFileSync("test/fixtures/js/whitespace.js")
});
it("should match require", function () {
matches = include_module.DIRECTIVE_REGEX.exec("= require src/blah.js")
should.exist(matches)
matches[0].should.eql('= require src/blah.js')
matches[1].should.eql('require')
matches[2].should.eql('src/blah.js')
})
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
it("should match require_tree", function () {
matches = include_module.DIRECTIVE_REGEX.exec("= require_tree src")
should.exist(matches)
matches[0].should.eql('= require_tree src')
matches[1].should.eql('require_tree')
matches[2].should.eql('src')
})
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/whitespace.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should include complex folder trees", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/include-trees.js",
contents: fs.readFileSync("test/fixtures/js/include-trees.js")
});
it("should match include", function () {
should.exist(matches)
matches = include_module.DIRECTIVE_REGEX.exec("= include src/blah.js")
matches[0].should.eql('= include src/blah.js')
matches[1].should.eql('include')
matches[2].should.eql('src/blah.js')
})
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
it("should match include_tree", function () {
matches = include_module.DIRECTIVE_REGEX.exec("= include_tree src")
should.exist(matches)
matches[0].should.eql('= include_tree src')
matches[1].should.eql('include_tree')
matches[2].should.eql('src')
})
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/include-trees.js"), "utf8"))
done();
});
testInclude.write(file);
});
})
it("should not REQUIRE a file twice", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/big-dummy-project-file.js",
contents: fs.readFileSync("test/fixtures/js/big-dummy-project-file.js")
});
it("should not match 'var x = require(blah)'", function () {
matches = include_module.DIRECTIVE_REGEX.exec("var x = require('fakemod')")
should.not.exist(matches)
})
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
it("should match relative requires", function () {
matches = include_module.DIRECTIVE_REGEX.exec("= include ../src/blah.js")
should.exist(matches)
matches[0].should.eql('= include ../src/blah.js')
matches[1].should.eql('include')
matches[2].should.eql('../src/blah.js')
})
})
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/big-dummy-project-file.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should pull files recursively", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/recursive.js",
contents: fs.readFileSync("test/fixtures/js/recursive.js")
});
describe("File replacing", function () {
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
it("should replace special comments with file contents", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/app.js",
contents: fs.readFileSync("test/fixtures/app.js")
});
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/recursive.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should only include files with the set extensions, if provided", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/js/options-extensions.js",
contents: fs.readFileSync("test/fixtures/js/options-extensions.js")
});
testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
testInclude = include({
extensions: ".txt"
});
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/app_all_extensions.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should only include the files with the provided SINGLE extension", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/app.js",
contents: fs.readFileSync("test/fixtures/app.js")
});
testInclude = include({
extensions: "txt"
});
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/app_only_txt.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should only include the files with the provided MULTIPLE extensions", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/app.js",
contents: fs.readFileSync("test/fixtures/app.js")
});
testInclude = include({
extensions: ["txt", "js"]
});
testInclude.on("data", function (newFile) {
should.exist(newFile);
should.exist(newFile.contents);
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/app_multiple_extensions.js"), "utf8"))
done();
});
testInclude.write(file);
});
it("should include files with a relative path", function (done) {
var file = new gutil.File({
base: "test/fixtures/relative/",
path: "test/fixtures/relative/app.js",
contents: fs.readFileSync("test/fixtures/relative/app.js")
});
testInclude = include({
extensions: ['js']
})
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/relative.js'), "utf8"))
done()
})
testInclude.write(file)
})
it("Should work on recursive includes", function (done) {
var file = new gutil.File({
base: "test/fixtures/",
path: "test/fixtures/app_recursive.js",
contents: fs.readFileSync("test/fixtures/app_recursive.js")
});
testInclude = include({
extensions: ['js']
})
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/app_recursive.js'), "utf8"))
done()
})
testInclude.write(file)
})
it("Should work on glob includes", function (done) {
var file = new gutil.File({
base: "test/fixtures/globs/",
path: "test/fixtures/globs/app.js",
contents: fs.readFileSync("test/fixtures/globs/app.js")
});
testInclude = include({
extensions: ['js']
})
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/app_globs.js'), "utf8"))
done()
});
testInclude.write(file)
})
it("Should match leading whitespace", function (done) {
var file = new gutil.File({
base: "test/fixtures/whitespace/",
path: "test/fixtures/whitespace/a.js",
contents: fs.readFileSync("test/fixtures/whitespace/a.js")
});
var testInclude = include({
extensions: 'js'
})
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/whitespace.js'), "utf8"))
done()
});
testInclude.write(file)
})
it("Should retain origin file's leading whitespace", function (done) {
var file = new gutil.File({
base: "test/fixtures/whitespace/",
path: "test/fixtures/whitespace/a_origin.js",
contents: fs.readFileSync("test/fixtures/whitespace/a_origin.js")
});
var testInclude = include({
extensions: 'js'
})
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/whitespace_origin.js'), "utf8"))
done()
});
testInclude.write(file)
})
it("Should work with css files", function (done) {
var file = new gutil.File({
base: "test/fixtures/styles/",
path: "test/fixtures/styles/a.css",
contents: fs.readFileSync("test/fixtures/styles/a.css")
});
var testInclude = include();
testInclude.on("data", function (newFile) {
should.exist(newFile)
should.exist(newFile.contents)
String(newFile.contents).should.equal(String(fs.readFileSync('test/expected/styles.css'), "utf8"))
done()
});
testInclude.write(file)
})
})
});
String(newFile.contents).should.equal(String(fs.readFileSync("test/expected/js/options-extensions.js"), "utf8"))
done();
});
testInclude.write(file);
});
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc