-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.js
127 lines (105 loc) · 3.46 KB
/
utils.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
'use strict';
const path = require('path');
const assign = Object.assign;
const { Transform } = require('readable-stream');
const noop = (data, enc, next) => next(null, data);
const define = (obj, key, fn) => Reflect.defineProperty(obj, key, { get: fn });
define(exports, 'combine', () => require('stream-combiner'));
define(exports, 'vfs', () => require('vinyl-fs'));
define(exports, 'src', () => require('vinyl-fs/lib/src'));
define(exports, 'dest', () => require('vinyl-fs/lib/dest'));
define(exports, 'symlink', () => require('vinyl-fs/lib/symlink'));
/**
* This function does all of the path-specific operations that
* `prepareWrite` does in http://github.com/wearefractal/vinyl-fs,
* but on a **cloned file**, which accomplishes two things:
*
* 1. We can merge the dest path information onto the context so
* that it can be used to calculate relative paths for navigation,
* pagination, etc.
* 2. Since we use a cloned file, we're not risking any double-processing
* on the actual view when it's finally written to the file system
* by the `.dest()` method.
*
* @param {Object} view
* @param {String|Function} dest
* @param {Object} options
*/
exports.prepare = function(app, view, dest, options = {}) {
if (view.preparedDest === true) return;
let file = new view.constructor(view);
let cwd = app.paths.templates;
let destDir = typeof dest === 'function' ? dest(file) : dest;
if (typeof destDir !== 'string') {
throw new TypeError('expected destination directory to be a string');
}
let baseDir = typeof options.base === 'function'
? options.base(file)
: path.resolve(cwd, destDir);
if (typeof baseDir !== 'string') {
throw new TypeError('expected base directory to be a string');
}
let writePath = path.join(destDir, view.basename);
let data = {};
data.cwd = cwd;
data.base = baseDir;
data.dest = destDir;
data.path = writePath;
view.preparedDest = true;
return data;
};
/**
* This sets up an event listener that will eventually
* be called by `app.renderFile()`, ensuring that `dest`
* information is loaded onto the context before rendering,
* so that views can render relative paths.
*/
exports.prepareDest = function fn(app, dest, options) {
app.emit('dest', dest, options);
let appOpts = assign({}, this.options);
delete appOpts.engine;
delete appOpts.tasks;
let opts = assign({}, appOpts, options);
if (fn.prepare) {
app.off('prepareDest', fn.prepare);
}
fn.prepare = view => {
let data = exports.prepare(app, view, dest, opts);
view.data = assign({}, view.data, data);
};
app.on('prepareDest', fn.prepare);
};
exports.through = (options, transform, flush) => {
if (typeof options === 'function') {
flush = transform;
transform = options;
options = null;
}
if (!transform) {
transform = noop;
}
if (transform.length === 2) {
let fn = transform;
transform = (data, enc, cb) => fn(data, cb);
}
let stream = new Transform({ transform, flush, ...options });
stream.setMaxListeners(0);
return stream;
};
exports.through.obj = (options, transform, flush) => {
if (typeof options === 'function') {
flush = transform;
transform = options;
options = null;
}
let opts = Object.assign({ objectMode: true, highWaterMark: 16 }, options);
return exports.through(opts, transform, flush);
};
exports.define = function(obj, key, value) {
Reflect.defineProperty(obj, key, {
configurable: true,
enumerable: false,
writable: true,
value
});
};