1 | 'use strict';
|
2 |
|
3 | const debug = require('debug')('tarima:compile');
|
4 |
|
5 | const path = require('path');
|
6 |
|
7 | const _worker = require('./_worker');
|
8 | const support = require('../../lib/support');
|
9 |
|
10 | module.exports = (context, files, cb) => {
|
11 | const tasks = [];
|
12 |
|
13 | const dispatch = context.dispatch;
|
14 | const copy = context.copy;
|
15 | const cache = context.cache;
|
16 | const match = context.match;
|
17 | const options = context.opts;
|
18 |
|
19 | if (!_worker.shared) {
|
20 | _worker.shared = _worker.init(options);
|
21 | }
|
22 |
|
23 | const onDelete = context.emit.bind(null, 'delete');
|
24 |
|
25 | const seen = {};
|
26 | const unknown = [];
|
27 |
|
28 | const watchers = !Array.isArray(options.watching)
|
29 | ? [options.watching]
|
30 | : options.watching;
|
31 |
|
32 | const watching = file => {
|
33 | for (let i = 0, c = watchers.length; i < c; i += 1) {
|
34 | if (file.indexOf(watchers[i]) === 0) {
|
35 | return true;
|
36 | }
|
37 | }
|
38 | };
|
39 |
|
40 | debug('Processing %s files', files.length);
|
41 |
|
42 | function append(src, next) {
|
43 | const entry = cache.get(src);
|
44 |
|
45 | if (entry.dirty === false) {
|
46 | delete entry.dirty;
|
47 | }
|
48 |
|
49 | if (entry.dirty) {
|
50 | next(src);
|
51 | }
|
52 | }
|
53 |
|
54 | function compile(src) {
|
55 | const entry = cache.get(src) || {};
|
56 |
|
57 |
|
58 | entry.main = true;
|
59 |
|
60 | if (entry.deleted) {
|
61 | context.dist({
|
62 | src,
|
63 | type: 'delete',
|
64 | dest: entry.dest,
|
65 | });
|
66 |
|
67 | cache.rm(src);
|
68 | onDelete(src, entry);
|
69 | } else {
|
70 | tasks.push({ src });
|
71 | }
|
72 | }
|
73 |
|
74 | function dest(id, ext) {
|
75 | return path.relative(options.cwd, path.join(options.output, ext
|
76 | ? id.replace(/\.[\w.]+$/, `.${ext}`)
|
77 | : id));
|
78 | }
|
79 |
|
80 | files.forEach(src => {
|
81 |
|
82 | if (watching(src) || copy(src)) {
|
83 | debug('WATCH %s', src);
|
84 | return;
|
85 | }
|
86 |
|
87 | const entry = cache.get(src);
|
88 |
|
89 | if (!entry) {
|
90 |
|
91 | cache.set(src, { dirty: true });
|
92 | }
|
93 |
|
94 | if (!support.isSupported(src)) {
|
95 | return append(src, id => {
|
96 | if (match(src)) {
|
97 | debug('OK %s', id);
|
98 |
|
99 | seen[id] = 1;
|
100 | unknown.push(id);
|
101 | } else {
|
102 | debug('SKIP %s', id);
|
103 | }
|
104 | });
|
105 | }
|
106 |
|
107 | if (!seen[src]) {
|
108 | seen[src] = true;
|
109 |
|
110 | if (match(src)) {
|
111 | debug('ADD %s', src);
|
112 | append(src, compile);
|
113 | } else {
|
114 | debug('SKIP %s', src);
|
115 | }
|
116 | } else {
|
117 | debug('SEEN %s', src);
|
118 | }
|
119 | });
|
120 |
|
121 | const _subtasks = [];
|
122 | const _files = [];
|
123 |
|
124 | if (unknown.length) {
|
125 | dispatch(options, unknown.map(file => {
|
126 | const _target = {
|
127 | src: file,
|
128 | dest: dest(file),
|
129 | };
|
130 |
|
131 | return _target;
|
132 | }), (result, next) => {
|
133 | Array.prototype.push.apply(tasks, result.map(x => {
|
134 | if (typeof options.rename === 'function') {
|
135 | options.rename(x);
|
136 | }
|
137 | return x;
|
138 | }));
|
139 |
|
140 | _subtasks.push(next((err, _result) => {
|
141 | if (!err) {
|
142 | Array.prototype.push.apply(_files, _result.map(x => x.dest));
|
143 | }
|
144 | }));
|
145 | });
|
146 | }
|
147 |
|
148 | function _end(err, output) {
|
149 | cb(err, {
|
150 | files,
|
151 | output,
|
152 | cache: cache.all(),
|
153 | input: Object.keys(seen),
|
154 | });
|
155 | }
|
156 |
|
157 | Promise.all(_subtasks)
|
158 | .then(() => {
|
159 | return tasks.map(task => () => new Promise((resolve, reject) => {
|
160 | _worker.run(task, options, (err, result, caching) => {
|
161 | if (err) {
|
162 | reject(err);
|
163 | } else {
|
164 | cache.set(task.src, caching);
|
165 | cache.set(task.src, 'dirty', false);
|
166 |
|
167 | (caching.deps || []).forEach(dep => {
|
168 | const parent = cache.get(dep) || {};
|
169 | const deps = parent.deps || [];
|
170 |
|
171 | cache.set(dep, 'dirty', false);
|
172 |
|
173 | if (deps.indexOf(task.src) === -1) {
|
174 | deps.push(task.src);
|
175 | cache.set(dep, 'deps', deps);
|
176 | }
|
177 | });
|
178 |
|
179 | result.forEach(x => {
|
180 | if (_files.indexOf(x) === -1) {
|
181 | _files.push(x);
|
182 | }
|
183 | });
|
184 |
|
185 | resolve();
|
186 | }
|
187 | });
|
188 | }))
|
189 | .reduce((prev, cur) => prev.then(() => cur()), Promise.resolve());
|
190 | })
|
191 | .then(() => _end(null, _files)).catch(e => _end(e, _files));
|
192 | };
|