UNPKG

13 kBMarkdownView Raw
1<p align="center">
2 <a href="https://gulpjs.com">
3 <img height="257" width="114" src="https://raw.githubusercontent.com/gulpjs/artwork/master/gulp-2x.png">
4 </a>
5</p>
6
7# vinyl
8
9[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coveralls Status][coveralls-image]][coveralls-url]
10
11Virtual file format.
12
13## What is Vinyl?
14
15Vinyl is a very simple metadata object that describes a file. When you think of a file, two attributes come to mind: `path` and `contents`. These are the main attributes on a Vinyl object. A file does not necessarily represent something on your computer’s file system. You have files on S3, FTP, Dropbox, Box, CloudThingly.io and other services. Vinyl can be used to describe files from all of these sources.
16
17## What is a Vinyl Adapter?
18
19While Vinyl provides a clean way to describe a file, we also need a way to access these files. Each file source needs what I call a "Vinyl adapter". A Vinyl adapter simply exposes a `src(globs)` and a `dest(folder)` method. Each return a stream. The `src` stream produces Vinyl objects, and the `dest` stream consumes Vinyl objects. Vinyl adapters can expose extra methods that might be specific to their input/output medium, such as the `symlink` method [`vinyl-fs`][vinyl-fs] provides.
20
21## Usage
22
23```js
24var Vinyl = require('vinyl');
25
26var jsFile = new Vinyl({
27 cwd: '/',
28 base: '/test/',
29 path: '/test/file.js',
30 contents: Buffer.from('var x = 123'),
31});
32```
33
34## API
35
36### `new Vinyl([options])`
37
38The constructor is used to create a new instance of `Vinyl`. Each instance represents a separate file, directory or symlink.
39
40All internally managed paths (`cwd`, `base`, `path`, `history`) are normalized and have trailing separators removed. See [Normalization and concatenation][normalization] for more information.
41
42Options may be passed upon instantiation to create a file with specific properties.
43
44#### `options`
45
46Options are not mutated by the constructor.
47
48##### `options.cwd`
49
50The current working directory of the file.
51
52Type: `String`
53
54Default: `process.cwd()`
55
56##### `options.base`
57
58Used for calculating the `relative` property. This is typically where a glob starts.
59
60Type: `String`
61
62Default: `options.cwd`
63
64##### `options.path`
65
66The full path to the file.
67
68Type: `String`
69
70Default: `undefined`
71
72##### `options.history`
73
74Stores the path history. If `options.path` and `options.history` are both passed, `options.path` is appended to `options.history`. All `options.history` paths are normalized by the `file.path` setter.
75
76Type: `Array`
77
78Default: `[]` (or `[options.path]` if `options.path` is passed)
79
80##### `options.stat`
81
82The result of an `fs.stat` call. This is how you mark the file as a directory or symbolic link. See [isDirectory()][is-directory], [isSymbolic()][is-symbolic] and [fs.Stats][fs-stats] for more information.
83
84Type: [`fs.Stats`][fs-stats]
85
86Default: `undefined`
87
88##### `options.contents`
89
90The contents of the file. If `options.contents` is a [`ReadableStream`][readable-stream], it is wrapped in a [`cloneable-readable`][cloneable-readable] stream.
91
92Type: [`ReadableStream`][readable-stream], [`Buffer`][buffer], or `null`
93
94Default: `null`
95
96##### `options.{custom}`
97
98Any other option properties will be directly assigned to the new Vinyl object.
99
100```js
101var Vinyl = require('vinyl');
102
103var file = new Vinyl({ foo: 'bar' });
104file.foo === 'bar'; // true
105```
106
107### Instance methods
108
109Each Vinyl object will have instance methods. Every method will be available but may return differently based on what properties were set upon instantiation or modified since.
110
111#### `file.isBuffer()`
112
113Returns `true` if the file contents are a [`Buffer`][buffer], otherwise `false`.
114
115#### `file.isStream()`
116
117Returns `true` if the file contents are a [`Stream`][stream], otherwise `false`.
118
119#### `file.isNull()`
120
121Returns `true` if the file contents are `null`, otherwise `false`.
122
123#### `file.isDirectory()`
124
125Returns `true` if the file represents a directory, otherwise `false`.
126
127A file is considered a directory when:
128
129- `file.isNull()` is `true`
130- `file.stat` is an object
131- `file.stat.isDirectory()` returns `true`
132
133When constructing a Vinyl object, pass in a valid [`fs.Stats`][fs-stats] object via `options.stat`. If you are mocking the [`fs.Stats`][fs-stats] object, you may need to stub the `isDirectory()` method.
134
135#### `file.isSymbolic()`
136
137Returns `true` if the file represents a symbolic link, otherwise `false`.
138
139A file is considered symbolic when:
140
141- `file.isNull()` is `true`
142- `file.stat` is an object
143- `file.stat.isSymbolicLink()` returns `true`
144
145When constructing a Vinyl object, pass in a valid [`fs.Stats`][fs-stats] object via `options.stat`. If you are mocking the [`fs.Stats`][fs-stats] object, you may need to stub the `isSymbolicLink()` method.
146
147#### `file.clone([options])`
148
149Returns a new Vinyl object with all attributes cloned.
150
151**By default custom attributes are cloned deeply.**
152
153If `options` or `options.deep` is `false`, custom attributes will not be cloned deeply.
154
155If `file.contents` is a [`Buffer`][buffer] and `options.contents` is `false`, the [`Buffer`][buffer] reference will be reused instead of copied.
156
157#### `file.inspect()`
158
159Returns a formatted-string interpretation of the Vinyl object. Automatically called by node's `console.log`.
160
161### Instance properties
162
163Each Vinyl object will have instance properties. Some may be unavailable based on what properties were set upon instantiation or modified since.
164
165#### `file.contents`
166
167Gets and sets the contents of the file. If set to a [`ReadableStream`][readable-stream], it is wrapped in a [`cloneable-readable`][cloneable-readable] stream.
168
169Throws when set to any value other than a [`ReadableStream`][readable-stream], a [`Buffer`][buffer] or `null`.
170
171Type: [`ReadableStream`][readable-stream], [`Buffer`][buffer], or `null`
172
173#### `file.cwd`
174
175Gets and sets current working directory. Will always be normalized and have trailing separators removed.
176
177Throws when set to any value other than non-empty strings.
178
179Type: `String`
180
181#### `file.base`
182
183Gets and sets base directory. Used for relative pathing (typically where a glob starts).
184When `null` or `undefined`, it simply proxies the `file.cwd` property. Will always be normalized and have trailing separators removed.
185
186Throws when set to any value other than non-empty strings or `null`/`undefined`.
187
188Type: `String`
189
190#### `file.path`
191
192Gets and sets the absolute pathname string or `undefined`. Setting to a different value appends the new path to `file.history`. If set to the same value as the current path, it is ignored. All new values are normalized and have trailing separators removed.
193
194Throws when set to any value other than a string.
195
196Type: `String`
197
198#### `file.history`
199
200Array of `file.path` values the Vinyl object has had, from `file.history[0]` (original) through `file.history[file.history.length - 1]` (current). `file.history` and its elements should normally be treated as read-only and only altered indirectly by setting `file.path`.
201
202Type: `Array`
203
204#### `file.relative`
205
206Gets the result of `path.relative(file.base, file.path)`.
207
208Throws when set or when `file.path` is not set.
209
210Type: `String`
211
212Example:
213
214```js
215var file = new File({
216 cwd: '/',
217 base: '/test/',
218 path: '/test/file.js',
219});
220
221console.log(file.relative); // file.js
222```
223
224#### `file.dirname`
225
226Gets and sets the dirname of `file.path`. Will always be normalized and have trailing separators removed.
227
228Throws when `file.path` is not set.
229
230Type: `String`
231
232Example:
233
234```js
235var file = new File({
236 cwd: '/',
237 base: '/test/',
238 path: '/test/file.js',
239});
240
241console.log(file.dirname); // /test
242
243file.dirname = '/specs';
244
245console.log(file.dirname); // /specs
246console.log(file.path); // /specs/file.js
247```
248
249#### `file.basename`
250
251Gets and sets the basename of `file.path`.
252
253Throws when `file.path` is not set.
254
255Type: `String`
256
257Example:
258
259```js
260var file = new File({
261 cwd: '/',
262 base: '/test/',
263 path: '/test/file.js',
264});
265
266console.log(file.basename); // file.js
267
268file.basename = 'file.txt';
269
270console.log(file.basename); // file.txt
271console.log(file.path); // /test/file.txt
272```
273
274#### `file.stem`
275
276Gets and sets stem (filename without suffix) of `file.path`.
277
278Throws when `file.path` is not set.
279
280Type: `String`
281
282Example:
283
284```js
285var file = new File({
286 cwd: '/',
287 base: '/test/',
288 path: '/test/file.js',
289});
290
291console.log(file.stem); // file
292
293file.stem = 'foo';
294
295console.log(file.stem); // foo
296console.log(file.path); // /test/foo.js
297```
298
299#### `file.extname`
300
301Gets and sets extname of `file.path`.
302
303Throws when `file.path` is not set.
304
305Type: `String`
306
307Example:
308
309```js
310var file = new File({
311 cwd: '/',
312 base: '/test/',
313 path: '/test/file.js',
314});
315
316console.log(file.extname); // .js
317
318file.extname = '.txt';
319
320console.log(file.extname); // .txt
321console.log(file.path); // /test/file.txt
322```
323
324#### `file.symlink`
325
326Gets and sets the path where the file points to if it's a symbolic link. Will always be normalized and have trailing separators removed.
327
328Throws when set to any value other than a string.
329
330Type: `String`
331
332### `Vinyl.isVinyl(file)`
333
334Static method used for checking if an object is a Vinyl file. Use this method instead of `instanceof`.
335
336Takes an object and returns `true` if it is a Vinyl file, otherwise returns `false`.
337
338**Note: This method uses an internal flag that some older versions of Vinyl didn't expose.**
339
340Example:
341
342```js
343var Vinyl = require('vinyl');
344
345var file = new Vinyl();
346var notAFile = {};
347
348Vinyl.isVinyl(file); // true
349Vinyl.isVinyl(notAFile); // false
350```
351
352### `Vinyl.isCustomProp(property)`
353
354Static method used by Vinyl when setting values inside the constructor or when copying properties in `file.clone()`.
355
356Takes a string `property` and returns `true` if the property is not used internally, otherwise returns `false`.
357
358This method is useful for inheritting from the Vinyl constructor. Read more in [Extending Vinyl][extending-vinyl].
359
360Example:
361
362```js
363var Vinyl = require('vinyl');
364
365Vinyl.isCustomProp('sourceMap'); // true
366Vinyl.isCustomProp('path'); // false -> internal getter/setter
367```
368
369## Normalization and concatenation
370
371Since all properties are normalized in their setters, you can just concatenate with `/`, and normalization takes care of it properly on all platforms.
372
373Example:
374
375```js
376var file = new File();
377file.path = '/' + 'test' + '/' + 'foo.bar';
378
379console.log(file.path);
380// posix => /test/foo.bar
381// win32 => \\test\\foo.bar
382```
383
384But never concatenate with `\`, since that is a valid filename character on posix system.
385
386## Extending Vinyl
387
388When extending Vinyl into your own class with extra features, you need to think about a few things.
389
390When 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.
391
392```js
393var Vinyl = require('vinyl');
394
395var builtInProps = ['foo', '_foo'];
396
397class SuperFile extends Vinyl {
398 constructor(options) {
399 super(options);
400 this._foo = 'example internal read-only value';
401 }
402
403 get foo() {
404 return this._foo;
405 }
406
407 static isCustomProp(name) {
408 return super.isCustomProp(name) && builtInProps.indexOf(name) === -1;
409 }
410}
411
412// `foo` won't be assigned to the object below
413new SuperFile({ foo: 'something' });
414```
415
416This makes properties `foo` and `_foo` skipped when passed in options to `constructor(options)` so they don't get assigned to the new object and override your custom implementation. They also won't be copied when cloning. **Note:** The `_foo` and `foo` properties will still exist on the created/cloned object because you are assigning `_foo` in the constructor and `foo` is defined on the prototype.
417
418Same goes for `clone()`. If you have your own internal stuff that needs special handling during cloning, you should extend it to do so.
419
420## License
421
422MIT
423
424<!-- prettier-ignore-start -->
425[downloads-image]: https://img.shields.io/npm/dm/vinyl.svg?style=flat-square
426[npm-url]: https://www.npmjs.com/package/vinyl
427[npm-image]: https://img.shields.io/npm/v/vinyl.svg?style=flat-square
428
429[ci-url]: https://github.com/gulpjs/vinyl/actions?query=workflow:dev
430[ci-image]: https://img.shields.io/github/workflow/status/gulpjs/vinyl/dev?style=flat-square
431
432[coveralls-url]: https://coveralls.io/r/gulpjs/vinyl
433[coveralls-image]: https://img.shields.io/coveralls/gulpjs/vinyl/master.svg?style=flat-square
434<!-- prettier-ignore-end -->
435
436<!-- prettier-ignore-start -->
437[is-symbolic]: #issymbolic
438[is-directory]: #isdirectory
439[normalization]: #normalization-and-concatenation
440[extending-vinyl]: #extending-vinyl
441[stream]: https://nodejs.org/api/stream.html#stream_stream
442[readable-stream]: https://nodejs.org/api/stream.html#stream_readable_streams
443[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
444[fs-stats]: https://nodejs.org/api/fs.html#fs_class_fs_stats
445[vinyl-fs]: https://github.com/gulpjs/vinyl-fs
446[cloneable-readable]: https://github.com/mcollina/cloneable-readable
447<!-- prettier-ignore-end -->