UNPKG

21.5 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: [{ type: reporter_resolve_1.ReportTypes.NoTasksAvailable }]
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: [{ type: reporter_resolve_1.ReportTypes.DocsInvalidTasksSimple }]
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