UNPKG

2.69 kBJavaScriptView Raw
1"use strict"
2
3const p = require("path")
4const Promise = require("bluebird")
5const wrapp = require("./wrapp")
6const util = require("./utils")
7const boot = require("./boot")
8const $ = require("./fn")
9
10const RGX = /[\\|\/]/g
11const co = Promise.coroutine
12const normalize = p.normalize
13const format = p.format
14const parse = p.parse
15const sep = p.sep
16
17function Task(ctx) {
18 // construct shape
19 this.$ = util
20 this.root = ctx.root
21 this._ = {files: [], globs: [], prevs: []}
22 // attach parent fns to Task
23 this.parallel = ctx.parallel.bind(ctx)
24 this.serial = ctx.serial.bind(ctx)
25 this.start = ctx.start.bind(ctx)
26 this.emit = ctx.emit.bind(ctx)
27 // attach `ctx.plugins` to prototype
28 for (const k in ctx.plugins) {
29 this[k] = ctx.plugins[k].bind(this)
30 }
31 // return chained methods + shared
32 return boot(this)
33}
34
35Task.prototype.exec = function(fn, opts, data) {
36 // cache ref to `ctx.tasks[].data` values
37 this._ = data
38 return fn.call(this, this, opts)
39}
40
41Task.prototype.run = co(function * (opts, func) {
42 return yield wrapp(opts, func).call(this)
43})
44
45Task.prototype.source = co(function * (globs, opts) {
46 globs = $.flatten($.toArray(globs))
47 const files = yield this.$.expand(globs, opts)
48
49 if (globs.length && !files.length) {
50 this.emit("globs_no_match", globs, opts)
51 }
52
53 // pre-fetch each file"s content
54 const datas = yield Promise.all(files.map(f => this.$.read(f)))
55
56 // update known globs
57 this._.globs = globs
58 // update known files, as (mod"d) `pathObject`s
59 this._.files = files.map((el, idx) => {
60 const obj = parse(el)
61 return {
62 dir: normalize(obj.dir),
63 data: datas[idx],
64 base: obj.base
65 }
66 })
67})
68
69Task.prototype.target = co(function * (dirs, opts) {
70 dirs = $.flatten($.toArray(dirs))
71 opts = opts || {}
72
73 const files = this._.files
74 // using `watcher`? original globs passed as `prevs`
75 // non-wildcard glob segments that should be trimmed!
76 const globs = (this._.prevs && this._.prevs.length > 0) ? this._.prevs : this._.globs
77
78 const trims = globs.map(g => {
79 let seg = g.split(RGX)
80 const idx = seg.findIndex(str => str.includes("*"))
81
82 if (idx === -1) {
83 seg.pop()
84 } else {
85 seg = seg.slice(0, idx)
86 }
87
88 return normalize(seg.join(sep))
89 }).sort((a, b) => b.length - a.length)
90
91 const tLength = trims.length
92
93 return yield Promise.all(
94 $.flatten(
95 files.map(obj => dirs.map(d => {
96 let i = 0
97 // clone `pathObject` per target dir
98 const o = { dir: obj.dir, base: obj.base }
99 // replace `source` segments with `target` dir
100 for (; i < tLength; i++) {
101 o.dir = o.dir.replace(trims[i], d)
102 }
103 // create final filepath & write to it!
104 return this.$.write(format(o), obj.data, opts)
105 }))
106 )
107 )
108})
109
110module.exports = Task