UNPKG

4.89 kBJavaScriptView Raw
1'use strict';
2
3const async = require('async');
4const fs = require('fs');
5const pth = require('path');
6const dict = require('./dictionary');
7const exitCodes = require('./exit-codes');
8const report = require('./report');
9const utils = require('./utils');
10const yaspeller = require('./yaspeller');
11const glob = require('glob');
12
13function hasData(err, data) {
14 return !err && data && Array.isArray(data.data) && data.data.length;
15}
16
17function onResource(err, data, originalText) {
18 if (hasData(err, data)) {
19 data.data = dict.removeDictWords(data.data);
20 data.data = yaspeller.removeDuplicates(data.data);
21
22 yaspeller.addPositions(originalText, data.data);
23 yaspeller.sortByPositions(data.data);
24
25 }
26
27 if (!process.exitCode && hasData(err, data)) {
28 process.exitCode = exitCodes.HAS_TYPOS;
29 }
30
31 if (err) {
32 process.exitCode = exitCodes.ERROR_LOADING;
33 }
34
35 report.oneach(err, data);
36}
37
38module.exports = {
39 /**
40 * Expand glob arguments.
41 *
42 * @param {string[]} args
43 * @returns {string[]}
44 */
45 expandGlobArgs(args) {
46 let result = [];
47
48 for (const value of args) {
49 if (utils.isUrl(value)) {
50 result.push(value);
51 } else {
52 const files = glob.sync(value);
53 if (files) {
54 result = result.concat(files);
55 }
56 }
57 }
58
59 return result;
60 },
61 /**
62 * Prepare tasks for resources.
63 *
64 * @param {Array} resources
65 * @param {Object} settings
66 * @returns {Array}
67 */
68 forResources(resources, settings) {
69 return this.expandGlobArgs(resources).map(resource => callback => {
70 if (utils.isUrl(resource)) {
71 this.forUrl(resource, settings, callback);
72 } else {
73 if (fs.existsSync(resource)) {
74 this.forFiles(resource, settings, callback);
75 } else {
76 onResource(true, Error(`${resource}: is not exists`));
77 callback();
78 }
79 }
80 });
81 },
82 /**
83 * Prepare task for stdin.
84 *
85 * @param {Object} settings
86 * @param {string} [filename]
87 * @returns {Array}
88 */
89 forStdin(settings, filename) {
90 return [function(callback) {
91 let text = '';
92
93 process.stdin
94 .setEncoding('utf8')
95 .on('readable', () => {
96 const chunk = process.stdin.read();
97 if (chunk !== null) {
98 text += chunk;
99 }
100 })
101 .on('end', function() {
102 const startTime = Date.now();
103 yaspeller.checkText(text, (err, data, originalText) => {
104 onResource(
105 err,
106 err ? data : {
107 resource: filename || 'stdin',
108 data: data,
109 time: Date.now() - startTime
110 },
111 originalText
112 );
113 callback();
114 }, settings);
115 });
116 }];
117 },
118 /**
119 * Prepare tasks for files.
120 *
121 * @param {string} resource
122 * @param {Object} settings
123 * @param {Function} callback
124 */
125 forFiles(resource, settings, callback) {
126 if (utils.isDir(resource)) {
127 const tasks = utils
128 .findFiles(resource, settings.fileExtensions, settings.excludeFiles)
129 .map(file => cb => yaspeller.checkFile(file, (err, data, originalText) => {
130 onResource(err, data, originalText);
131 cb();
132 }, settings));
133
134 async.parallelLimit(tasks, settings.maxRequests, callback);
135 } else {
136 const file = pth.resolve(resource);
137 if (utils.isExcludedFile(file, settings.excludeFiles)) {
138 callback();
139 } else {
140 yaspeller.checkFile(file, (err, data, originalText) => {
141 onResource(err, data, originalText);
142 callback();
143 }, settings);
144 }
145 }
146 },
147 /**
148 * Prepare tasks for a url.
149 *
150 * @param {string} resource
151 * @param {Object} settings
152 * @param {Function} callback
153 */
154 forUrl(resource, settings, callback) {
155 if (utils.isSitemap(resource)) {
156 yaspeller.checkSitemap(resource, callback, settings, onResource);
157 } else {
158 yaspeller.checkUrl(resource, (err, data, originalText) => {
159 onResource(err, data, originalText);
160 callback();
161 }, settings);
162 }
163 }
164};