UNPKG

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