diff --git a/README.md b/README.md
index a33e588..29df968 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
## Information
-
+
| Package | vinyl |
@@ -34,35 +34,35 @@ var coffeeFile = new File({
#### options.cwd
-Type: `String`
+Type: `String`
Default: `process.cwd()`
#### options.base
Used for relative pathing. Typically where a glob starts.
-Type: `String`
+Type: `String`
Default: `options.cwd`
#### options.path
Full path to the file.
-Type: `String`
+Type: `String`
Default: `null`
#### options.stat
The result of an fs.stat call. See [fs.Stats](http://nodejs.org/api/fs.html#fs_class_fs_stats) for more information.
-Type: `fs.Stats`
+Type: `fs.Stats`
Default: `null`
#### options.contents
File contents.
-Type: `Buffer, Stream, or null`
+Type: `Buffer, Stream, or null`
Default: `null`
### isBuffer()
@@ -77,9 +77,16 @@ Returns true if file.contents is a Stream.
Returns true if file.contents is null.
-### clone()
+### clone(options)
+
+Returns a new File object with all attributes cloned. Custom attributes that
+may have been added to the File object are deep-cloned (using the Lodash
+cloneDeep function) into the new File.
+
+#### options.contents
-Returns a new File object with all attributes cloned.
+If file.contents is a Buffer, and options.contents is false, it will
+reference-copy the buffer instead of cloning it.
### pipe(stream[, opt])
@@ -120,4 +127,4 @@ console.log(file.relative); // file.coffee
[coveralls-url]: https://coveralls.io/r/wearefractal/vinyl
[coveralls-image]: https://coveralls.io/repos/wearefractal/vinyl/badge.png
[depstat-url]: https://david-dm.org/wearefractal/vinyl
-[depstat-image]: https://david-dm.org/wearefractal/vinyl.png
\ No newline at end of file
+[depstat-image]: https://david-dm.org/wearefractal/vinyl.png
diff --git a/index.js b/index.js
index 58c3632..438a127 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,7 @@
var path = require('path');
var cloneStats = require('clone-stats');
+var cloneDeep = require('lodash.clonedeep');
var isBuffer = require('./lib/isBuffer');
var isStream = require('./lib/isStream');
@@ -42,17 +43,27 @@ File.prototype.isDirectory = function() {
return this.isNull() && this.stat && this.stat.isDirectory();
};
-File.prototype.clone = function() {
- var clonedContents = this.isBuffer() ? cloneBuffer(this.contents) : this.contents;
- var clonedStat = this.stat ? cloneStats(this.stat) : null;
-
- return new File({
- cwd: this.cwd,
- base: this.base,
- path: this.path,
- stat: clonedStat,
- contents: clonedContents
- });
+File.prototype.clone = function(opt) {
+ if (!opt) opt = {};
+
+ var clone = new File();
+
+ Object.keys(this).forEach(function(key) {
+ if (key !== '_contents' && key !== 'stat' && this.hasOwnProperty(key)) {
+ clone[key] = cloneDeep(this[key]);
+ }
+ }, this);
+
+ if (opt.contents !== false && this.isBuffer()) {
+ clone.contents = cloneBuffer(this.contents);
+ }
+ else {
+ clone.contents = this.contents;
+ }
+
+ clone.stat = this.stat ? cloneStats(this.stat) : null;
+
+ return clone;
};
File.prototype.pipe = function(stream, opt) {
diff --git a/package.json b/package.json
index d851cb1..739f378 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
"author": "Fractal (http://wearefractal.com/)",
"main": "./index.js",
"dependencies": {
- "clone-stats": "~0.0.1"
+ "clone-stats": "~0.0.1",
+ "lodash.clonedeep": "^2.4.1"
},
"devDependencies": {
"mocha": "~1.17.0",
diff --git a/test/File.js b/test/File.js
index 1f2a83a..79c9306 100644
--- a/test/File.js
+++ b/test/File.js
@@ -80,7 +80,7 @@ describe('File', function() {
done();
});
});
-
+
describe('isBuffer()', function() {
it('should return true when the contents are a Buffer', function(done) {
var val = new Buffer("test");
@@ -250,6 +250,48 @@ describe('File', function() {
done();
});
+
+ it('should copy custom properties', function(done) {
+ var options = {
+ cwd: "/",
+ base: "/test/",
+ path: "/test/test.coffee",
+ contents: null
+ };
+ var file = new File(options);
+ file.customProp = 'a custom property';
+
+ var file2 = file.clone();
+
+ file2.should.not.equal(file, 'refs should be different');
+ file2.cwd.should.equal(file.cwd);
+ file2.base.should.equal(file.base);
+ file2.path.should.equal(file.path);
+ file2.customProp.should.equal(file.customProp);
+
+ done();
+ });
+
+ it('should allow to reference-copy a Buffer', function(done) {
+ var options = {
+ cwd: "/",
+ base: "/test/",
+ path: "/test/test.coffee",
+ contents: new Buffer("test")
+ };
+ var file = new File(options);
+
+ var file2 = file.clone({ contents: false });
+
+ file2.should.not.equal(file, 'refs should be different');
+ file2.cwd.should.equal(file.cwd);
+ file2.base.should.equal(file.base);
+ file2.path.should.equal(file.path);
+ file2.contents.should.equal(file.contents, 'buffer ref should be the same');
+ file2.contents.toString('utf8').should.equal(file.contents.toString('utf8'));
+
+ done();
+ });
});
describe('pipe()', function() {
@@ -382,7 +424,7 @@ describe('File', function() {
process.nextTick(done);
});
});
-
+
describe('inspect()', function() {
it('should return correct format when no contents and no path', function(done) {
var file = new File();
@@ -445,7 +487,7 @@ describe('File', function() {
done();
});
});
-
+
describe('contents get/set', function() {
it('should work with Buffer', function(done) {
var val = new Buffer("test");