# Code coverage report for vinyl/index.js

## Statements: 100% (89 / 89) Branches: 100% (76 / 76) Functions: 100% (15 / 15) Lines: 100% (82 / 82) Ignored: none

All files » vinyl/ » index.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    1761
    1
    1
    1
    1
    1
    1
    1
    1

    1
    73

    73
    73

    73
    73

    73

    73

    1
    26

    1
    29

    1
    6

    1
    3

    1
    14
    2

    12
    7

    5
    5

    14
    14
    1
    1
    13
    6

    14

    14

    75

    70

    5

    14

    1
    6
    6

    6
    2

    4
    2
    1

    1

    2

    2
    2

    1
    6

    6

    6
    4

    6
    3

    6
    1

    6

    1

    99

    78
    1

    77

    1

    7
    6
    5

    1

    1

    46

    9

    8
    5

    1
     var path = require('path');
    var clone = require('lodash').clone;
    var cloneStats = require('clone-stats');
    var cloneBuffer = require('./lib/cloneBuffer');
    var isBuffer = require('./lib/isBuffer');
    var isStream = require('./lib/isStream');
    var isNull = require('./lib/isNull');
    var inspectStream = require('./lib/inspectStream');
    var Stream = require('stream');

    function File(file) {
      if (!file) file = {};

      // record path change
      var history = file.path ? [file.path] : file.history;
      this.history = history || [];

      // TODO: should this be moved to vinyl-fs?
      this.cwd = file.cwd || process.cwd();
      this.base = file.base || this.cwd;

      // stat = fs stats object
      // TODO: should this be moved to vinyl-fs?
      this.stat = file.stat || null;

      // contents = stream, buffer, or null if not read
      this.contents = file.contents || null;
    }

    File.prototype.isBuffer = function() {
      return isBuffer(this.contents);
    };

    File.prototype.isStream = function() {
      return isStream(this.contents);
    };

    File.prototype.isNull = function() {
      return isNull(this.contents);
    };

    // TODO: should this be moved to vinyl-fs?
    File.prototype.isDirectory = function() {
      return this.isNull() && this.stat && this.stat.isDirectory();
    };

    File.prototype.clone = function(opt) {
      if (typeof opt === 'boolean') {
        opt = {
          deep: opt,
          contents: true
        };
      } else if (!opt) {
        opt = {
          deep: false,
          contents: true
        };
      } else {
        opt.deep = opt.deep === true;
        opt.contents = opt.contents !== false;
      }

      // clone our file contents
      var contents;
      if (this.isStream()) {
        contents = this.contents.pipe(new Stream.PassThrough());
        this.contents = this.contents.pipe(new Stream.PassThrough());
      } else if (this.isBuffer()) {
        contents = opt.contents ? cloneBuffer(this.contents) : this.contents;
      }

      var file = new File({
        cwd: this.cwd,
        base: this.base,
        stat: (this.stat ? cloneStats(this.stat) : null),
        history: this.history.slice(),
        contents: contents
      });

      // 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);
      return file;
    };

    File.prototype.pipe = function(stream, opt) {
      if (!opt) opt = {};
      if (typeof opt.end === 'undefined') opt.end = true;

      if (this.isStream()) {
        return this.contents.pipe(stream, opt);
      }
      if (this.isBuffer()) {
        if (opt.end) {
          stream.end(this.contents);
        } else {
          stream.write(this.contents);
        }
        return stream;
      }

      // isNull
      if (opt.end) stream.end();
      return stream;
    };

    File.prototype.inspect = function() {
      var inspect = [];

      // use relative path if possible
      var filePath = (this.base && this.path) ? this.relative : this.path;

      if (filePath) {
        inspect.push('"'+filePath+'"');
      }

      if (this.isBuffer()) {
        inspect.push(this.contents.inspect());
      }

      if (this.isStream()) {
        inspect.push(inspectStream(this.contents));
      }

      return '<File '+inspect.join(' ')+'>';
    };

    // virtual attributes
    // or stuff with extra logic
    Object.defineProperty(File.prototype, 'contents', {
      get: function() {
        return this._contents;
      },
      set: function(val) {
        if (!isBuffer(val) && !isStream(val) && !isNull(val)) {
          throw new Error('File.contents can only be a Buffer, a Stream, or null.');
        }
        this._contents = val;
      }
    });

    // TODO: should this be moved to vinyl-fs?
    Object.defineProperty(File.prototype, 'relative', {
      get: function() {
        if (!this.base) throw new Error('No base specified! Can not get relative.');
        if (!this.path) throw new Error('No path specified! Can not get relative.');
        return path.relative(this.base, this.path);
      },
      set: function() {
        throw new Error('File.relative is generated from the base and path attributes. Do not modify it.');
      }
    });

    Object.defineProperty(File.prototype, 'path', {
      get: function() {
        return this.history[this.history.length - 1];
      },
      set: function(path) {
        if (typeof path !== 'string') throw new Error('path should be string');

        // record history only when path changed
        if (path && path !== this.path) {
          this.history.push(path);
        }
      }
    });

    module.exports = File;