UNPKG

21.3 kBJavaScriptView Raw
1"use strict";
2var command_run_1 = require("./command.run");
3var task_resolve_1 = require("./task.resolve");
4var Rx = require("rx");
5var reporter_resolve_1 = require("./reporter.resolve");
6var task_utils_1 = require("./task.utils");
7var fs_1 = require("fs");
8var file = require("./file.utils");
9var defaultReporter_1 = require("./reporters/defaultReporter");
10var logger_1 = require("./logger");
11var debug = require("debug")("cb:command:docs");
12(function (DocsErrorTypes) {
13 DocsErrorTypes[DocsErrorTypes["DocsInputFileNotFound"] = "DocsInputFileNotFound"] = "DocsInputFileNotFound";
14 DocsErrorTypes[DocsErrorTypes["DocsOutputFileExists"] = "DocsOutputFileExists"] = "DocsOutputFileExists";
15})(exports.DocsErrorTypes || (exports.DocsErrorTypes = {}));
16var DocsErrorTypes = exports.DocsErrorTypes;
17exports.docStartComment = "<!--crossbow-docs-start-->";
18exports.docEndComment = "<!--crossbow-docs-end-->";
19exports.hasRegExp = /<!--crossbow-docs-start-->([\s\S]+?)?<!--crossbow-docs-end-->/g;
20exports.hasExistingComments = function (inputString) { return exports.hasRegExp.test(inputString); };
21exports.readmeRegExp = /readme\.(md|markdown)$/i;
22function execute(trigger) {
23 var input = trigger.input, config = trigger.config, reporter = trigger.reporter;
24 /**
25 * Resolve all top-level tasks as these are the ones
26 * that will used in the docs
27 * @type {Tasks}
28 */
29 var toResolve = task_utils_1.getPossibleTaskNames(input);
30 var tasks = task_resolve_1.resolveTasks(toResolve
31 .filter(task_utils_1.isPublicTask)
32 .filter(function (x) { return !task_utils_1.isInternal(x); }), trigger);
33 /**
34 * If there were 0 tasks, exit with error
35 */
36 if (tasks.all.length === 0) {
37 reporter({ type: reporter_resolve_1.ReportTypes.NoTasksAvailable });
38 return Rx.Observable.just({
39 setup: {
40 tasks: tasks,
41 errors: []
42 }
43 });
44 }
45 debug("Amount of tasks to consider " + tasks.all.length);
46 /**
47 * If any tasks were invalid, refuse to generate docs
48 * and prompt to run tasks command (for the full error output)
49 */
50 if (tasks.invalid.length) {
51 debug("Tasks were invalid, so skipping doc generation completely");
52 reporter({ type: reporter_resolve_1.ReportTypes.DocsInvalidTasksSimple });
53 return Rx.Observable.just({
54 setup: {
55 tasks: tasks,
56 errors: []
57 }
58 });
59 }
60 var markdown = getMarkdown(tasks.valid);
61 /**
62 * If the user provided the --file flag,
63 * try to load that file & either wedge in the new docs or
64 * append them
65 */
66 if (config.file) {
67 return Rx.Observable.just({ setup: handleFileFlag(tasks, markdown, trigger) });
68 }
69 /**
70 * If a user provides the 'output' flag, it means they want a new file creating
71 */
72 if (config.output) {
73 return Rx.Observable.just({ setup: handleOutputFlag(tasks, markdown, trigger) });
74 }
75 /**
76 * If both --flag and --output were NOT given, look for a readme in this current
77 * directory
78 * @type {Array}
79 */
80 var existingReadmeFiles = fs_1.readdirSync(process.cwd())
81 .filter(function (x) { return exports.readmeRegExp.test(x); })
82 .reduce(function (acc, item) { return acc.concat(file.readFilesFromDiskWithContent([item], config.cwd)); }, []);
83 if (existingReadmeFiles.length) {
84 var output_1 = existingReadmeFiles.map(function (x) { return getFileOutput(x, markdown); });
85 reportAddToDocs(output_1, trigger);
86 return Rx.Observable.just({
87 setup: {
88 errors: [],
89 tasks: tasks,
90 markdown: markdown,
91 output: output_1
92 }
93 });
94 }
95 /**
96 * At this point:
97 * 1. NO --file flag given
98 * 2. NO --output flag given
99 * 3. NO existing readme files in cwd
100 *
101 * so, create a new one :)
102 */
103 var output = [{
104 file: file.getStubFile("readme.md", config.cwd),
105 content: markdown
106 }];
107 reportAddToDocs(output, trigger);
108 return Rx.Observable.just({
109 setup: {
110 errors: [],
111 tasks: tasks,
112 markdown: markdown,
113 output: output
114 }
115 });
116}
117/**
118 * When adding docs to a file
119 * 1. if file content does not exist, use raw markdown
120 * 2. if docs exist, replace them
121 * 3. if 1 & 2 fail, append
122 */
123function getFileOutput(file, markdown) {
124 /**
125 * If there's no exisitng file content, just use the markdown
126 */
127 if (!file.content) {
128 debug(file.relative + " DOES NOT have any content");
129 return { file: file, content: markdown };
130 }
131 /**
132 * If there's existing docs, wedge.
133 */
134 if (exports.hasExistingComments(file.content)) {
135 debug(file.relative + " has the comments already in the file, so will replace");
136 var replaced = file.content.replace(exports.hasRegExp, markdown);
137 return {
138 file: file,
139 content: replaced
140 };
141 }
142 debug(file.relative + " DOES NOT have the comments, so will append to the end of the file");
143 return {
144 file: file,
145 content: file.content + "\n" + markdown
146 };
147}
148/**
149 * When the --output flag was given
150 *
151 * eg:
152 *
153 * $ crossbow docs --output newfile.md
154 */
155function handleOutputFlag(tasks, markdown, trigger) {
156 var config = trigger.config, reporter = trigger.reporter;
157 var maybe = file.readFilesFromDiskWithContent([config.output], config.cwd);
158 var available = maybe
159 .filter(function (x) { return x.errors.length > 0; })
160 .filter(function (x) { return x.errors[0].type === task_utils_1.InputErrorTypes.FileNotFound; });
161 if (!available.length) {
162 var error = { type: DocsErrorTypes.DocsOutputFileExists, file: maybe[0] };
163 if (!config.handoff) {
164 reporter({ type: reporter_resolve_1.ReportTypes.DocsOutputFileExists, data: { error: error } });
165 }
166 return {
167 errors: [error],
168 tasks: tasks,
169 markdown: markdown,
170 output: []
171 };
172 }
173 var output = [{
174 file: maybe[0],
175 content: markdown
176 }];
177 // Now we can report about writing to disk
178 reportAddToDocs(output, trigger);
179 return {
180 errors: [],
181 tasks: tasks,
182 markdown: markdown,
183 output: output
184 };
185}
186/**
187 * When the --file flag was given.
188 *
189 * eg:
190 *
191 * $ crossbow docs --file readme.md
192 */
193function handleFileFlag(tasks, markdown, trigger) {
194 var config = trigger.config, reporter = trigger.reporter;
195 /**
196 * Try to read the file from disk with content appended
197 * @type {file.ExternalFileContent[]}
198 */
199 var maybes = file.readFilesFromDiskWithContent([config.file], config.cwd);
200 var withErrors = maybes
201 .filter(function (x) { return x.errors.length > 0; })
202 .map(function (x) {
203 return {
204 type: DocsErrorTypes.DocsInputFileNotFound,
205 file: x
206 };
207 });
208 /**
209 * If the --file flag produced an error,
210 * eg: --file shane.md -> but shane.md did not exist
211 */
212 if (withErrors.length) {
213 /**
214 * If we're not handing off, report the error
215 */
216 if (!config.handoff) {
217 reporter({ type: reporter_resolve_1.ReportTypes.DocsInputFileNotFound, data: { error: withErrors[0] } });
218 }
219 return {
220 errors: withErrors,
221 tasks: tasks,
222 markdown: markdown,
223 output: []
224 };
225 }
226 /**
227 * At this point we have files to work with so we
228 * either append the docs or insert them between existing
229 * comments
230 * @type {{content: string, file: file.ExternalFileContent}[]}
231 */
232 var output = maybes.map(function (x) { return getFileOutput(x, markdown); });
233 /**
234 * Now write to file
235 */
236 reportAddToDocs(output, trigger);
237 /**
238 * Always return everything gathered
239 */
240 return {
241 errors: [],
242 tasks: tasks,
243 markdown: markdown,
244 output: output
245 };
246}
247function getMarkdown(tasks) {
248 /**
249 * Create the header for the markdown table
250 * @type {string|string[]}
251 */
252 var tasksHeader = ["## Crossbow tasks\n\nThe following tasks have been defined by this project's Crossbow configuration.\nRun any of them in the following way\n \n```shell\n$ crossbow run <taskname>\n```"];
253 var tableHeader = "|Task name|Description|\n|---|---|";
254 /**
255 * Create the body for the table with taskname + description
256 * @type {string[]}
257 */
258 var body = tasks.map(function (task) {
259 var isParent = task.type === task_resolve_1.TaskTypes.ParentGroup;
260 var name = (function () {
261 if (isParent) {
262 return "|<pre>`" + task.baseTaskName + ":" + task.subTasks[0] + "`</pre>";
263 }
264 return "|<pre>`" + task.baseTaskName + "`</pre>";
265 })();
266 var desc = (function () {
267 if (task.description)
268 return task_utils_1.removeNewlines(task.description);
269 if (isParent) {
270 if (task.tasks[0].description) {
271 return task_utils_1.removeNewlines(task.tasks[0].description);
272 }
273 }
274 if (task.tasks.length) {
275 var subject = task.tasks;
276 return ["**Alias for:**"]
277 .concat(subject
278 .map(function (x) { return ("- `" + defaultReporter_1.getLabel(x) + "`"); })
279 .map(function (x) { return logger_1.clean(x); }))
280 .join("<br>");
281 }
282 })() + "|";
283 return [name, desc].join("|");
284 }).join("\n");
285 /**
286 * Join the lines with a \n for correct formatting in markdown
287 * @type {string}
288 */
289 return [exports.docStartComment, tasksHeader, tableHeader, body, exports.docEndComment].join("\n");
290}
291function reportAddToDocs(output, trigger) {
292 var config = trigger.config;
293 if (!config.handoff) {
294 output.forEach(function (x) {
295 trigger.reporter({
296 type: reporter_resolve_1.ReportTypes.DocsAddedToFile,
297 data: {
298 file: x.file
299 }
300 });
301 });
302 }
303}
304function handleIncomingDocsCommand(cli, input, config, reporter) {
305 return execute({
306 cli: cli,
307 input: input,
308 config: config,
309 reporter: reporter,
310 type: command_run_1.TriggerTypes.command
311 });
312}
313Object.defineProperty(exports, "__esModule", { value: true });
314exports.default = handleIncomingDocsCommand;
315//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWFuZC5kb2NzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmQuZG9jcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsNEJBQTJDLGVBQWUsQ0FBQyxDQUFBO0FBRzNELDZCQUE2QyxnQkFBZ0IsQ0FBQyxDQUFBO0FBRTlELElBQU8sRUFBRSxXQUFXLElBQUksQ0FBQyxDQUFDO0FBQzFCLGlDQUEwQixvQkFBb0IsQ0FBQyxDQUFBO0FBRS9DLDJCQUE4RixjQUFjLENBQUMsQ0FBQTtBQUM3RyxtQkFBMEIsSUFBSSxDQUFDLENBQUE7QUFDL0IsSUFBWSxJQUFJLFdBQU0sY0FBYyxDQUFDLENBQUE7QUFFckMsZ0NBQXVCLDZCQUE2QixDQUFDLENBQUE7QUFDckQsdUJBQW9CLFVBQVUsQ0FBQyxDQUFBO0FBRS9CLElBQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBU2xELFdBQVksY0FBYztJQUN0Qix5REFBNkIsdUJBQXVCLDJCQUFBLENBQUE7SUFDcEQsd0RBQTRCLHNCQUFzQiwwQkFBQSxDQUFBO0FBQ3RELENBQUMsRUFIVyxzQkFBYyxLQUFkLHNCQUFjLFFBR3pCO0FBSEQsSUFBWSxjQUFjLEdBQWQsc0JBR1gsQ0FBQTtBQUNZLHVCQUFlLEdBQUcsNEJBQTRCLENBQUM7QUFDL0MscUJBQWEsR0FBRywwQkFBMEIsQ0FBQztBQUMzQyxpQkFBUyxHQUFHLGdFQUFnRSxDQUFDO0FBQzdFLDJCQUFtQixHQUFHLFVBQUMsV0FBVyxJQUFLLE9BQUEsaUJBQVMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQTNCLENBQTJCLENBQUM7QUFDbkUsb0JBQVksR0FBRyx5QkFBeUIsQ0FBQztBQWV0RCxpQkFBaUIsT0FBdUI7SUFFN0IseUJBQUssRUFBRSx1QkFBTSxFQUFFLDJCQUFRLENBQVk7SUFFMUM7Ozs7T0FJRztJQUNILElBQU0sU0FBUyxHQUFHLGlDQUFvQixD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
\No newline at end of file