Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make constructor set custom properties #92

Merged
merged 5 commits into from
Jul 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ File.isVinyl(dummy); // true
File.isVinyl(notAFile); // false
```

### isCustomProp
Vinyl checks if a property is not managed internally, such as `sourceMap`. This is than used in `constructor(options)` when setting, and `clone()` when copying properties.

```js
var File = require('vinyl');

File.isCustomProp('sourceMap'); // true
File.isCustomProp('path'); // false -> internal getter/setter
```

Read more in [Extending Vinyl](#extending-vinyl).

### constructor(options)
#### options.cwd
Type: `String`<br><br>Default: `process.cwd()`
Expand Down Expand Up @@ -61,6 +73,16 @@ File contents.

Type: `Buffer, Stream, or null`<br><br>Default: `null`

#### options.{custom}
Any other option properties will just be assigned to the new File object.

```js
var File = require('vinyl');

var file = new File({foo: 'bar'});
file.foo === 'bar'; // true
```

### isBuffer()
Returns true if file.contents is a Buffer.

Expand Down Expand Up @@ -203,6 +225,36 @@ console.log(file.extname); // .js
console.log(file.path); // /test/file.js
```

## Extending Vinyl
When extending Vinyl into your own class with extra features, you need to think about a few things.

When you have your own properties that are managed internally, you need to extend the static `isCustomProp` method to return `false` when one of these properties is queried.

```js
const File = require('vinyl');

const builtInProps = ['foo', '_foo'];

class SuperFile extends File {
constructor(options) {
super(options);
this._foo = 'example internal read-only value';
}

get foo() {
return this._foo;
}

static isCustomProp(name) {
return super.isCustomProp(name) && builtInProps.indexOf(name) === -1;
}
}
```

This makes properties `foo` and `_foo` ignored when cloning, and when passed in options to `constructor(options)` so they don't get assigned to the new object.

Same goes for `clone()`. If you have your own internal stuff that needs special handling during cloning, you should extend it to do so.

[npm-url]: https://npmjs.org/package/vinyl
[npm-image]: https://badge.fury.io/js/vinyl.svg
[travis-url]: https://travis-ci.org/gulpjs/vinyl
Expand Down
31 changes: 23 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ var inspectStream = require('./lib/inspectStream');
var Stream = require('stream');
var replaceExt = require('replace-ext');

var builtInFields = [
'_contents', 'contents', 'stat', 'history', 'path', 'base', 'cwd',
];

function File(file) {
var self = this;

if (!file) {
file = {};
}
Expand All @@ -28,6 +34,13 @@ function File(file) {
this.contents = file.contents || null;

this._isVinyl = true;

// Set custom properties
Object.keys(file).forEach(function(key) {
if (self.constructor.isCustomProp(key)) {
self[key] = file[key];
}
});
}

File.prototype.isBuffer = function() {
Expand All @@ -48,6 +61,8 @@ File.prototype.isDirectory = function() {
};

File.prototype.clone = function(opt) {
var self = this;

if (typeof opt === 'boolean') {
opt = {
deep: opt,
Expand Down Expand Up @@ -82,14 +97,10 @@ File.prototype.clone = function(opt) {

// Clone our custom properties
Object.keys(this).forEach(function(key) {
// Ignore built-in fields
if (key === '_contents' || key === 'stat' ||
key === 'history' || key === 'path' ||
key === 'base' || key === 'cwd') {
return;
}
file[key] = opt.deep ? clone(this[key], true) : this[key];
}, this);
if (self.constructor.isCustomProp(key)) {
file[key] = opt.deep ? clone(self[key], true) : self[key];
}
});
return file;
};

Expand Down Expand Up @@ -141,6 +152,10 @@ File.prototype.inspect = function() {
return '<File ' + inspect.join(' ') + '>';
};

File.isCustomProp = function(key) {
return builtInFields.indexOf(key) === -1;
};

File.isVinyl = function(file) {
return (file && file._isVinyl === true) || false;
};
Expand Down
7 changes: 7 additions & 0 deletions test/File.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ describe('File', function() {
file.contents.should.equal(val);
done();
});

it('should set custom properties', function(done) {
var sourceMap = {};
var file = new File({ sourceMap: sourceMap });
file.sourceMap.should.equal(sourceMap);
done();
});
});

describe('isBuffer()', function() {
Expand Down