@automattic/vip 2.22.0 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +38 -13
  2. package/assets/dev-env.lando.template.yml.ejs +6 -1
  3. package/dist/bin/vip-app-list.js +0 -12
  4. package/dist/bin/vip-app.js +6 -13
  5. package/dist/bin/vip-cache-purge-url.js +4 -19
  6. package/dist/bin/vip-cache.js +0 -2
  7. package/dist/bin/vip-config-envvar-delete.js +4 -19
  8. package/dist/bin/vip-config-envvar-get-all.js +6 -19
  9. package/dist/bin/vip-config-envvar-get.js +4 -15
  10. package/dist/bin/vip-config-envvar-list.js +8 -20
  11. package/dist/bin/vip-config-envvar-set.js +4 -23
  12. package/dist/bin/vip-config-envvar.js +0 -2
  13. package/dist/bin/vip-config-software-get.js +0 -17
  14. package/dist/bin/vip-config-software-update.js +6 -22
  15. package/dist/bin/vip-config-software.js +0 -2
  16. package/dist/bin/vip-config.js +0 -2
  17. package/dist/bin/vip-dev-env-create.js +8 -21
  18. package/dist/bin/vip-dev-env-destroy.js +4 -11
  19. package/dist/bin/vip-dev-env-exec.js +4 -14
  20. package/dist/bin/vip-dev-env-import-media.js +3 -8
  21. package/dist/bin/vip-dev-env-import-sql.js +10 -23
  22. package/dist/bin/vip-dev-env-import.js +0 -3
  23. package/dist/bin/vip-dev-env-info.js +5 -13
  24. package/dist/bin/vip-dev-env-list.js +4 -9
  25. package/dist/bin/vip-dev-env-start.js +9 -17
  26. package/dist/bin/vip-dev-env-stop.js +4 -11
  27. package/dist/bin/vip-dev-env-update.js +4 -12
  28. package/dist/bin/vip-dev-env.js +0 -2
  29. package/dist/bin/vip-import-media-abort.js +0 -18
  30. package/dist/bin/vip-import-media-status.js +0 -12
  31. package/dist/bin/vip-import-media.js +6 -23
  32. package/dist/bin/vip-import-sql-status.js +0 -12
  33. package/dist/bin/vip-import-sql.js +33 -99
  34. package/dist/bin/vip-import-validate-files.js +21 -42
  35. package/dist/bin/vip-import-validate-sql.js +0 -8
  36. package/dist/bin/vip-import.js +0 -3
  37. package/dist/bin/vip-logs.js +20 -50
  38. package/dist/bin/vip-search-replace.js +8 -14
  39. package/dist/bin/vip-sync.js +2 -25
  40. package/dist/bin/vip-validate-preflight.js +467 -0
  41. package/dist/bin/vip-validate.js +19 -0
  42. package/dist/bin/vip-whoami.js +2 -14
  43. package/dist/bin/vip-wp.js +39 -89
  44. package/dist/bin/vip.js +14 -40
  45. package/dist/lib/analytics/clients/pendo.js +9 -18
  46. package/dist/lib/analytics/clients/stub.js +1 -3
  47. package/dist/lib/analytics/clients/tracks.js +11 -20
  48. package/dist/lib/analytics/index.js +4 -11
  49. package/dist/lib/api/app.js +1 -11
  50. package/dist/lib/api/cache-purge.js +4 -7
  51. package/dist/lib/api/feature-flags.js +1 -4
  52. package/dist/lib/api/http.js +9 -15
  53. package/dist/lib/api/user.js +1 -7
  54. package/dist/lib/api.js +7 -18
  55. package/dist/lib/app-logs/app-logs.js +2 -9
  56. package/dist/lib/app.js +2 -5
  57. package/dist/lib/cli/apiConfig.js +4 -19
  58. package/dist/lib/cli/command.js +43 -133
  59. package/dist/lib/cli/config.js +1 -5
  60. package/dist/lib/cli/envAlias.js +14 -15
  61. package/dist/lib/cli/exit.js +4 -6
  62. package/dist/lib/cli/format.js +8 -50
  63. package/dist/lib/cli/progress.js +13 -42
  64. package/dist/lib/cli/prompt.js +1 -5
  65. package/dist/lib/cli/repo.js +7 -20
  66. package/dist/lib/client-file-uploader.js +44 -97
  67. package/dist/lib/config/software.js +2 -52
  68. package/dist/lib/constants/dev-environment.js +1 -2
  69. package/dist/lib/constants/file-size.js +1 -1
  70. package/dist/lib/constants/vipgo.js +1 -1
  71. package/dist/lib/dev-environment/dev-environment-cli.js +140 -195
  72. package/dist/lib/dev-environment/dev-environment-core.js +91 -186
  73. package/dist/lib/dev-environment/dev-environment-lando.js +32 -96
  74. package/dist/lib/env.js +1 -4
  75. package/dist/lib/envvar/api-delete.js +1 -4
  76. package/dist/lib/envvar/api-get-all.js +1 -4
  77. package/dist/lib/envvar/api-get.js +1 -2
  78. package/dist/lib/envvar/api-list.js +3 -4
  79. package/dist/lib/envvar/api-set.js +1 -4
  80. package/dist/lib/envvar/api.js +5 -16
  81. package/dist/lib/envvar/input.js +1 -8
  82. package/dist/lib/envvar/logging.js +2 -6
  83. package/dist/lib/envvar/read-file.js +1 -3
  84. package/dist/lib/http/proxy-agent.js +17 -22
  85. package/dist/lib/keychain/browser.js +1 -4
  86. package/dist/lib/keychain/insecure.js +1 -10
  87. package/dist/lib/keychain/secure.js +1 -8
  88. package/dist/lib/keychain.js +4 -8
  89. package/dist/lib/logout.js +0 -6
  90. package/dist/lib/media-import/media-file-import.js +3 -7
  91. package/dist/lib/media-import/progress.js +6 -17
  92. package/dist/lib/media-import/status.js +14 -65
  93. package/dist/lib/read-file.js +1 -6
  94. package/dist/lib/rollbar.js +1 -7
  95. package/dist/lib/search-and-replace.js +9 -41
  96. package/dist/lib/site-import/db-file-import.js +3 -9
  97. package/dist/lib/site-import/status.js +17 -74
  98. package/dist/lib/token.js +1 -33
  99. package/dist/lib/tracker.js +4 -20
  100. package/dist/lib/user-error.js +0 -2
  101. package/dist/lib/validations/is-multi-site-sql-dump.js +4 -12
  102. package/dist/lib/validations/is-multi-site.js +5 -21
  103. package/dist/lib/validations/is-multisite-domain-mapped.js +5 -31
  104. package/dist/lib/validations/line-by-line.js +4 -16
  105. package/dist/lib/validations/site-type.js +10 -19
  106. package/dist/lib/validations/sql.js +11 -76
  107. package/dist/lib/validations/utils.js +1 -6
  108. package/dist/lib/vip-import-validate-files.js +82 -109
  109. package/npm-shrinkwrap.json +894 -357
  110. package/package.json +5 -2
@@ -3,62 +3,62 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.summaryLogs = exports.logErrorsForIntermediateImages = exports.logErrorsForInvalidFilenames = exports.logErrorsForInvalidFileTypes = exports.doesImageHaveExistingSource = exports.isFileSanitized = exports.folderStructureValidation = exports.findNestedDirectories = exports.acceptedExtensions = void 0;
7
-
6
+ exports.summaryLogs = exports.logErrorsForInvalidFilenames = exports.logErrorsForInvalidFileTypes = exports.logErrorsForIntermediateImages = exports.isFileSanitized = exports.folderStructureValidation = exports.findNestedDirectories = exports.doesImageHaveExistingSource = exports.acceptedExtensions = void 0;
8
7
  var _chalk = _interopRequireDefault(require("chalk"));
9
-
10
8
  var _fs = _interopRequireDefault(require("fs"));
11
-
12
9
  var _path = _interopRequireDefault(require("path"));
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
11
 
16
12
  /**
17
13
  * External dependencies
18
14
  */
15
+
19
16
  // Accepted media file extensions
20
17
  const acceptedExtensions = ['jpg', 'jpeg', 'jpe', 'gif', 'png', 'bmp', 'svg', 'tiff', 'tif', 'ico', 'asf', 'asx', 'wmv', 'wmx', 'wm', 'avi', 'divx', 'mov', 'qt', 'mpeg', 'mpg', 'mpe', 'mp4', 'm4v', 'ogv', 'webm', 'mkv', '3gp', '3gpp', '3g2', '3gp2', 'txt', 'asc', 'c', 'cc', 'h', 'srt', 'csv', 'tsv', 'ics', 'rtx', 'css', 'vtt', 'dfxp', 'mp3', 'm4a', 'm4b', 'ra', 'ram', 'wav', 'ogg', 'oga', 'mid', 'midi', 'wma', 'wax', 'mka', 'rtf', 'js', 'pdf', 'class', 'psd', 'xcf', 'doc', 'pot', 'pps', 'ppt', 'wri', 'xla', 'xls', 'xlt', 'xlw', 'mdb', 'mpp', 'docx', 'docm', 'dotx', 'dotm', 'xlsx', 'xlsm', 'xlsb', 'xltx', 'xltm', 'xlam', 'pptx', 'pptm', 'ppsx', 'ppsm', 'potx', 'potm', 'ppam', 'sldx', 'sldm', 'onetoc', ' onetoc2', 'onetmp', 'onepkg', 'oxps', 'xps', 'odt', 'odp', 'ods', 'odg', 'odc', 'odb', 'odf', 'webp', 'wp', 'wpd', 'key', 'numbers', 'pages'];
18
+
21
19
  /**
22
20
  * Character validation global variables
23
21
  *
24
22
  * Accepted and prohibited characters for filenames
25
23
  */
24
+
26
25
  // Accepted characters in filenames
27
26
  // eslint-disable-next-line max-len
28
-
29
27
  exports.acceptedExtensions = acceptedExtensions;
30
28
  const acceptedCharacters = ['Non-English characters', '(', ')', '[', ']', '~', '&', '#', '%', '=', '’', '\'', '×', '@', '`', '?', '*', '!', '\"', '\\', '<', '>', ':', ';', ',', '/', '$', '|', '`', '{', '}', 'spaces'];
31
29
  const acceptedCharactersSet = new Set(acceptedCharacters); // Prevent duplicates with a Set
32
- // Prohibited characters in filenames
33
30
 
31
+ // Prohibited characters in filenames
34
32
  const prohibitedCharacters = ['+', '%20'];
35
33
  const prohibitedCharactersSet = new Set(prohibitedCharacters);
34
+
36
35
  /**
37
36
  * Recommendations
38
37
  *
39
38
  * Recommend alternatives to invalid folders or files
40
39
  */
41
- // Recommend the WordPress year/month file structure for media files
42
40
 
41
+ // Recommend the WordPress year/month file structure for media files
43
42
  const recommendedFileStructure = () => {
44
43
  console.log(_chalk.default.underline('We recommend the WordPress default folder structure for your media files: \n\n') + _chalk.default.underline('Single sites:') + _chalk.default.yellow('`uploads/year/month/image.png`\n') + ' e.g.-' + _chalk.default.yellow('`uploads/2020/06/image.png`\n') + _chalk.default.underline('Multisites:') + _chalk.default.cyan('`uploads/sites/siteID/year/month/image.png`\n') + ' e.g.-' + _chalk.default.cyan('`uploads/sites/5/2020/06/images.png`\n'));
45
44
  console.log('------------------------------------------------------------');
46
45
  console.log();
47
- }; // Recommend accepted file types
48
-
46
+ };
49
47
 
48
+ // Recommend accepted file types
50
49
  const recommendAcceptableFileTypes = () => {
51
50
  console.log('Accepted file types: \n\n' + _chalk.default.magenta(`${acceptedExtensions}`));
52
51
  console.log();
53
- }; // Accepted file name characters
54
-
52
+ };
55
53
 
54
+ // Accepted file name characters
56
55
  const recommendAcceptableFileNames = () => {
57
56
  // const acceptedCharacters = 'Non-English characters, spaces, ( ) [ ] ~';
58
57
  const allowedCharacters = [...acceptedCharactersSet].join(' ');
59
58
  const notAllowedCharacters = [...prohibitedCharactersSet].join(' ');
60
59
  console.log('The following characters are allowed in file names:\n' + _chalk.default.green(`All special characters, including: ${allowedCharacters}\n\n`) + 'The following characters are prohibited in file names:\n' + _chalk.default.red(`Encoded or alternate whitespace, such as ${notAllowedCharacters}, are converted to proper spaces\n`));
61
60
  };
61
+
62
62
  /**
63
63
  * Nested Directory Search
64
64
  *
@@ -72,34 +72,30 @@ const recommendAcceptableFileNames = () => {
72
72
  *
73
73
  * @param {string} directory Root directory, or the given (current) directory
74
74
  */
75
-
76
-
77
75
  const files = [];
78
76
  const folderStructureObj = {};
79
-
80
77
  const findNestedDirectories = directory => {
81
78
  let nestedDirectories;
82
-
83
79
  try {
84
80
  // Read nested directories within the given directory
85
- nestedDirectories = _fs.default.readdirSync(directory); // Filter out hidden files such as .DS_Store
81
+ nestedDirectories = _fs.default.readdirSync(directory);
86
82
 
83
+ // Filter out hidden files such as .DS_Store
87
84
  nestedDirectories = nestedDirectories.filter(file => !/(^|\/)\.[^\/\.]/g.test(file));
88
85
  nestedDirectories.forEach(dir => {
89
86
  // Concatenate the file path of the parent directory with the nested directory
90
87
  const filePath = _path.default.join(directory, dir);
91
-
92
88
  const statSync = _fs.default.statSync(filePath); // Get stats on the file/folder
93
- // Keep looking for nested directories until we hit individual files
94
-
95
89
 
90
+ // Keep looking for nested directories until we hit individual files
96
91
  if (statSync.isDirectory()) {
97
92
  findNestedDirectories(filePath);
98
93
  } else {
99
94
  // Once we hit media files, add the path of all existing folders
100
95
  // as object keys to validate folder structure later on
101
- folderStructureObj[directory] = true; // Also, push individual files to an array to do individual file validations later on
96
+ folderStructureObj[directory] = true;
102
97
 
98
+ // Also, push individual files to an array to do individual file validations later on
103
99
  return files.push(filePath);
104
100
  }
105
101
  });
@@ -107,12 +103,12 @@ const findNestedDirectories = directory => {
107
103
  console.error(_chalk.default.red('✕'), ` Error: Cannot read nested directory: ${directory}. Reason: ${error.message}`);
108
104
  return;
109
105
  }
110
-
111
106
  return {
112
107
  files,
113
108
  folderStructureObj
114
109
  };
115
110
  };
111
+
116
112
  /**
117
113
  * Folder structure validation
118
114
  *
@@ -122,30 +118,27 @@ const findNestedDirectories = directory => {
122
118
  * @param {Boolean} sites Check if site is a multisite or single site
123
119
  * @return {Object} indexes
124
120
  */
125
-
126
-
127
121
  exports.findNestedDirectories = findNestedDirectories;
128
-
129
122
  const getIndexPositionOfFolders = (folderPath, sites) => {
130
123
  let sitesIndex, siteIDIndex, yearIndex, monthIndex;
131
124
  let pathMutate = folderPath; // Mutate `path` for multisites
132
- // Turn the path into an array to determine index position
133
125
 
126
+ // Turn the path into an array to determine index position
134
127
  const directories = pathMutate.split('/');
128
+
135
129
  /**
136
130
  * Upload folder
137
131
  *
138
132
  * Find if an `uploads` folder exists and return its index position
139
133
  */
140
-
141
134
  const uploadsIndex = directories.indexOf('uploads');
135
+
142
136
  /**
143
137
  * Multisite folder
144
138
  *
145
139
  * If a sites directory exists, find the directory and return its index position
146
140
  * Find if a siteID folder exists via regex, then obtain that value
147
141
  */
148
-
149
142
  if (sites) {
150
143
  sitesIndex = directories.indexOf('sites');
151
144
  const regexSiteID = /\/sites\/(\d+)/g;
@@ -153,42 +146,40 @@ const getIndexPositionOfFolders = (folderPath, sites) => {
153
146
 
154
147
  if (siteID) {
155
148
  siteIDIndex = directories.indexOf(siteID[1]);
156
- } // Remove the multisite-specific path to avoid confusing a 2 digit site ID with the month
157
- // e.g.- `uploads/sites/11/2020/06` -> `uploads/2020/06`
158
-
149
+ }
159
150
 
151
+ // Remove the multisite-specific path to avoid confusing a 2 digit site ID with the month
152
+ // e.g.- `uploads/sites/11/2020/06` -> `uploads/2020/06`
160
153
  pathMutate = pathMutate.replace(siteID[0], '');
161
154
  }
155
+
162
156
  /**
163
157
  * Year folder
164
158
  *
165
159
  * Find if a year folder exists via a four digit regex matching pattern,
166
160
  * then obtain that value
167
161
  */
168
-
169
-
170
162
  const regexYear = /\b\d{4}\b/g;
171
163
  const year = regexYear.exec(pathMutate); // Returns an array with the regex-matching value
172
164
 
173
165
  if (year) {
174
166
  yearIndex = directories.indexOf(year[0]);
175
167
  }
168
+
176
169
  /**
177
170
  * Month folder
178
171
  *
179
172
  * Find if a month folder exists via a two digit regex matching pattern,
180
173
  * then obtain that value
181
174
  */
182
-
183
-
184
175
  const regexMonth = /\b\d{2}\b/g;
185
176
  const month = regexMonth.exec(pathMutate); // Returns an array with the regex-matching value
186
177
 
187
178
  if (month) {
188
179
  monthIndex = directories.indexOf(month[0]);
189
- } // Multisite
190
-
180
+ }
191
181
 
182
+ // Multisite
192
183
  if (sites) {
193
184
  return {
194
185
  uploadsIndex,
@@ -197,15 +188,16 @@ const getIndexPositionOfFolders = (folderPath, sites) => {
197
188
  yearIndex,
198
189
  monthIndex
199
190
  };
200
- } // Single site
201
-
191
+ }
202
192
 
193
+ // Single site
203
194
  return {
204
195
  uploadsIndex,
205
196
  yearIndex,
206
197
  monthIndex
207
198
  };
208
199
  };
200
+
209
201
  /**
210
202
  * Single site folder structure validation
211
203
  *
@@ -218,23 +210,23 @@ const getIndexPositionOfFolders = (folderPath, sites) => {
218
210
  * @param {string} folderPath Path of the entire folder structure
219
211
  * @returns {string|null} Returns null if the folder structure is good; else, returns the folder path
220
212
  */
221
-
222
-
223
213
  const singleSiteValidation = folderPath => {
224
214
  let errors = 0; // Tally individual folder errors
225
215
 
226
- console.log(_chalk.default.bold('Folder:'), _chalk.default.cyan(`${folderPath}`)); // Use destructuring to retrieve the index position of each folder
216
+ console.log(_chalk.default.bold('Folder:'), _chalk.default.cyan(`${folderPath}`));
227
217
 
218
+ // Use destructuring to retrieve the index position of each folder
228
219
  const {
229
220
  uploadsIndex,
230
221
  yearIndex,
231
222
  monthIndex
232
223
  } = getIndexPositionOfFolders(folderPath);
224
+
233
225
  /**
234
226
  * Logging
235
227
  */
236
- // Uploads folder
237
228
 
229
+ // Uploads folder
238
230
  if (uploadsIndex === 0) {
239
231
  console.log();
240
232
  console.log('✅ File structure: Uploads directory exists');
@@ -242,17 +234,17 @@ const singleSiteValidation = folderPath => {
242
234
  console.log();
243
235
  console.log(_chalk.default.yellow('✕'), 'Recommended: Media files should reside in an', _chalk.default.magenta('`uploads`'), 'directory');
244
236
  errors++;
245
- } // Year folder
246
-
237
+ }
247
238
 
239
+ // Year folder
248
240
  if (yearIndex && yearIndex === 1) {
249
241
  console.log('✅ File structure: Year directory exists (format: YYYY)');
250
242
  } else {
251
243
  console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/YYYY`'), 'directories');
252
244
  errors++;
253
- } // Month folder
254
-
245
+ }
255
246
 
247
+ // Month folder
256
248
  if (monthIndex && monthIndex === 2) {
257
249
  console.log('✅ File structure: Month directory exists (format: MM)');
258
250
  console.log();
@@ -260,15 +252,15 @@ const singleSiteValidation = folderPath => {
260
252
  console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/YYYY/MM`'), 'directories');
261
253
  console.log();
262
254
  errors++;
263
- } // Push individual folder errors to the collective array of errors
264
-
255
+ }
265
256
 
257
+ // Push individual folder errors to the collective array of errors
266
258
  if (errors > 0) {
267
259
  return folderPath;
268
260
  }
269
-
270
261
  return null;
271
262
  };
263
+
272
264
  /**
273
265
  * Multisite folder structure validation
274
266
  *
@@ -282,13 +274,12 @@ const singleSiteValidation = folderPath => {
282
274
  * @param {string} folderPath Path of the entire folder structure
283
275
  * @returns {string|null} Returns null if the folder structure is good; else, returns the folder path
284
276
  */
285
-
286
-
287
277
  const multiSiteValidation = folderPath => {
288
278
  let errors = 0; // Tally individual folder errors
289
279
 
290
- console.log(_chalk.default.bold('Folder:'), _chalk.default.cyan(`${folderPath}`)); // Use destructuring to retrieve the index position of each folder
280
+ console.log(_chalk.default.bold('Folder:'), _chalk.default.cyan(`${folderPath}`));
291
281
 
282
+ // Use destructuring to retrieve the index position of each folder
292
283
  const {
293
284
  uploadsIndex,
294
285
  sitesIndex,
@@ -296,11 +287,12 @@ const multiSiteValidation = folderPath => {
296
287
  yearIndex,
297
288
  monthIndex
298
289
  } = getIndexPositionOfFolders(folderPath, true);
290
+
299
291
  /**
300
292
  * Logging
301
293
  */
302
- // Uploads folder
303
294
 
295
+ // Uploads folder
304
296
  if (uploadsIndex === 0) {
305
297
  console.log();
306
298
  console.log('✅ File structure: Uploads directory exists');
@@ -308,34 +300,34 @@ const multiSiteValidation = folderPath => {
308
300
  console.log();
309
301
  console.log(_chalk.default.yellow('✕'), 'Recommended: Media files should reside in an', _chalk.default.magenta('`uploads`'), 'directory');
310
302
  errors++;
311
- } // Sites folder
312
-
303
+ }
313
304
 
305
+ // Sites folder
314
306
  if (sitesIndex === 1) {
315
307
  console.log('✅ File structure: Sites directory exists');
316
308
  } else {
317
309
  console.log();
318
310
  console.log(_chalk.default.yellow('✕'), 'Recommended: Media files should reside in an', _chalk.default.magenta('`sites`'), 'directory');
319
311
  errors++;
320
- } // Site ID folder
321
-
312
+ }
322
313
 
314
+ // Site ID folder
323
315
  if (siteIDIndex && siteIDIndex === 2) {
324
316
  console.log('✅ File structure: Site ID directory exists');
325
317
  } else {
326
318
  console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/sites/<siteID>`'), 'directories');
327
319
  errors++;
328
- } // Year folder
329
-
320
+ }
330
321
 
322
+ // Year folder
331
323
  if (yearIndex && yearIndex === 3) {
332
324
  console.log('✅ File structure: Year directory exists (format: YYYY)');
333
325
  } else {
334
326
  console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/sites/<siteID>/YYYY`'), 'directories');
335
327
  errors++;
336
- } // Month folder
337
-
328
+ }
338
329
 
330
+ // Month folder
339
331
  if (monthIndex && monthIndex === 4) {
340
332
  console.log('✅ File structure: Month directory exists (format: MM)');
341
333
  console.log();
@@ -343,15 +335,15 @@ const multiSiteValidation = folderPath => {
343
335
  console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/sites/<siteID>/YYYY/MM`'), 'directories');
344
336
  console.log();
345
337
  errors++;
346
- } // Push individual folder errors to the collective array of errors
347
-
338
+ }
348
339
 
340
+ // Push individual folder errors to the collective array of errors
349
341
  if (errors > 0) {
350
342
  return folderPath;
351
343
  }
352
-
353
344
  return null;
354
345
  };
346
+
355
347
  /**
356
348
  * Folder structure validation
357
349
  *
@@ -360,15 +352,15 @@ const multiSiteValidation = folderPath => {
360
352
  * @param {Array} folderStructureKeys Array of paths for each folder
361
353
  * @return {Array} All the erroneous folder paths in an array
362
354
  */
363
-
364
-
365
355
  const folderStructureValidation = folderStructureKeys => {
366
356
  // Collect all the folder paths that aren't in the recommended structure
367
- const allErrors = []; // Loop through each path to validate the folder structure format
357
+ const allErrors = [];
368
358
 
359
+ // Loop through each path to validate the folder structure format
369
360
  for (const folderPath of folderStructureKeys) {
370
- let badFolders; // Check for multisite folder structure
361
+ let badFolders;
371
362
 
363
+ // Check for multisite folder structure
372
364
  if (folderPath.search('sites') !== -1) {
373
365
  // Returns null if the folder path is good, otherwise it returns the folder path itself
374
366
  badFolders = multiSiteValidation(folderPath);
@@ -376,18 +368,16 @@ const folderStructureValidation = folderStructureKeys => {
376
368
  // Returns null if the folder path is good, otherwise it returns the folder path itself
377
369
  badFolders = singleSiteValidation(folderPath);
378
370
  }
379
-
380
371
  if (badFolders) {
381
372
  allErrors.push(badFolders);
382
373
  }
383
374
  }
384
-
385
375
  if (allErrors.length > 0) {
386
376
  recommendedFileStructure();
387
377
  }
388
-
389
378
  return allErrors;
390
379
  };
380
+
391
381
  /**
392
382
  * Character validation
393
383
  *
@@ -397,22 +387,21 @@ const folderStructureValidation = folderStructureKeys => {
397
387
  * @param {string} file - The current file being validated
398
388
  * @returns {Boolean} - Checks if the filename has been sanitized
399
389
  */
400
-
401
-
402
390
  exports.folderStructureValidation = folderStructureValidation;
403
-
404
391
  const isFileSanitized = file => {
405
392
  const filename = _path.default.basename(file);
393
+ let sanitizedFile = filename;
406
394
 
407
- let sanitizedFile = filename; // Convert encoded or alternate whitespace into a proper space
395
+ // Convert encoded or alternate whitespace into a proper space
408
396
  // Encoded spaces (%20), no-break spaces - keeps words together (\u00A0), and plus signs
409
-
410
397
  const regexSpaces = /\u00A0|(%20)|\+/g;
411
- sanitizedFile = sanitizedFile.replace(regexSpaces, ' '); // Check if the filename has been sanitized
398
+ sanitizedFile = sanitizedFile.replace(regexSpaces, ' ');
412
399
 
400
+ // Check if the filename has been sanitized
413
401
  const checkFile = sanitizedFile !== filename;
414
402
  return checkFile;
415
403
  };
404
+
416
405
  /**
417
406
  * Intermediate image validation
418
407
  *
@@ -427,53 +416,47 @@ const isFileSanitized = file => {
427
416
  * @param {string} filename The current file being validated
428
417
  * @returns {Array} Returns an array of the matching regex characters
429
418
  */
430
-
431
-
432
419
  exports.isFileSanitized = isFileSanitized;
433
-
434
420
  const identifyIntermediateImage = filename => {
435
421
  const regex = /(-|_)?(\d+x\d+)(@\d+\w)?(\.\w{3,4})$/;
436
422
  return filename.match(regex);
437
- }; // Check if an intermediate image has an existing original (source) image
438
-
423
+ };
439
424
 
425
+ // Check if an intermediate image has an existing original (source) image
440
426
  const doesImageHaveExistingSource = file => {
441
- const filename = _path.default.basename(file); // Intermediate image regex check
442
-
427
+ const filename = _path.default.basename(file);
443
428
 
429
+ // Intermediate image regex check
444
430
  const intermediateImage = identifyIntermediateImage(filename);
445
-
446
431
  if (null !== intermediateImage) {
447
432
  const imageSizing = intermediateImage[0]; // First capture group of the regex validation
448
-
449
433
  const extension = _path.default.extname(filename).substr(1); // Extension of the path (e.g.- `.jpg`)
434
+
450
435
  // Filename manipulation: if an image is an intermediate image, strip away the image sizing
451
436
  // e.g.- `panda4000x6000.png` -> `panda.png`
452
-
453
-
454
437
  const baseFileName = filename.replace(imageSizing, '') + '.' + extension;
455
- const splitFolder = file.split('/'); // Remove the last element (intermediate image filename) and replace it with the original image filename
438
+ const splitFolder = file.split('/');
456
439
 
440
+ // Remove the last element (intermediate image filename) and replace it with the original image filename
457
441
  splitFolder.splice(splitFolder.length - 1, 1, baseFileName);
458
- const originalImage = splitFolder.join('/'); // Check if an image with the same path + name (the original) already exists
442
+ const originalImage = splitFolder.join('/');
459
443
 
444
+ // Check if an image with the same path + name (the original) already exists
460
445
  if (_fs.default.existsSync(originalImage)) {
461
446
  return originalImage;
462
447
  }
463
-
464
448
  return false;
465
449
  }
466
450
  };
451
+
467
452
  /**
468
453
  * Error logging
469
454
  *
470
455
  * Log errors for invalid folders or files
471
456
  */
472
- // Log errors for files with invalid file extensions and recommend accepted file types
473
-
474
457
 
458
+ // Log errors for files with invalid file extensions and recommend accepted file types
475
459
  exports.doesImageHaveExistingSource = doesImageHaveExistingSource;
476
-
477
460
  const logErrorsForInvalidFileTypes = invalidFiles => {
478
461
  invalidFiles.map(file => {
479
462
  console.error(_chalk.default.red('✕'), 'File extensions: Invalid file type for file: ', _chalk.default.cyan(`${file}`));
@@ -482,11 +465,10 @@ const logErrorsForInvalidFileTypes = invalidFiles => {
482
465
  recommendAcceptableFileTypes();
483
466
  console.log('------------------------------------------------------------');
484
467
  console.log();
485
- }; // Log errors for files with invalid filenames and show a list of accepted/prohibited chars
486
-
468
+ };
487
469
 
470
+ // Log errors for files with invalid filenames and show a list of accepted/prohibited chars
488
471
  exports.logErrorsForInvalidFileTypes = logErrorsForInvalidFileTypes;
489
-
490
472
  const logErrorsForInvalidFilenames = invalidFiles => {
491
473
  invalidFiles.map(file => {
492
474
  console.error(_chalk.default.red('✕'), 'Character validation: Invalid filename for file: ', _chalk.default.cyan(`${file}`));
@@ -495,21 +477,17 @@ const logErrorsForInvalidFilenames = invalidFiles => {
495
477
  recommendAcceptableFileNames();
496
478
  console.log('------------------------------------------------------------');
497
479
  console.log();
498
- }; // Log errors for intermediate image file duplicates
499
-
480
+ };
500
481
 
482
+ // Log errors for intermediate image file duplicates
501
483
  exports.logErrorsForInvalidFilenames = logErrorsForInvalidFilenames;
502
-
503
484
  const logErrorsForIntermediateImages = obj => {
504
485
  for (const original in obj) {
505
486
  console.error(_chalk.default.red('✕'), 'Intermediate images: Duplicate files found:\n' + 'Original file: ' + _chalk.default.blue(`${original}\n`) + 'Intermediate images: ' + _chalk.default.cyan(`${obj[original]}\n`));
506
487
  }
507
-
508
488
  console.log('------------------------------------------------------------');
509
489
  };
510
-
511
490
  exports.logErrorsForIntermediateImages = logErrorsForIntermediateImages;
512
-
513
491
  const summaryLogs = ({
514
492
  folderErrorsLength,
515
493
  intImagesErrorsLength,
@@ -523,26 +501,21 @@ const summaryLogs = ({
523
501
  } else {
524
502
  folderErrorsLength = _chalk.default.bgGreen(' PASS ') + _chalk.default.bold.green(` ${totalFolders} folders, `) + `${totalFolders} folders total`;
525
503
  }
526
-
527
504
  if (intImagesErrorsLength > 0) {
528
505
  intImagesErrorsLength = _chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${intImagesErrorsLength} intermediate images`) + `, ${totalFiles} files total`;
529
506
  } else {
530
507
  intImagesErrorsLength = _chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${intImagesErrorsLength} intermediate images`) + `, ${totalFiles} files total`;
531
508
  }
532
-
533
509
  if (fileTypeErrorsLength > 0) {
534
510
  fileTypeErrorsLength = _chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${fileTypeErrorsLength} invalid file extensions`) + `, ${totalFiles} files total`;
535
511
  } else {
536
512
  fileTypeErrorsLength = _chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${fileTypeErrorsLength} invalid file extensions`) + `, ${totalFiles} files total`;
537
513
  }
538
-
539
514
  if (filenameErrorsLength) {
540
515
  filenameErrorsLength = _chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`;
541
516
  } else {
542
517
  filenameErrorsLength = _chalk.default.bgGreen(' PASS ') + _chalk.default.green(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`;
543
518
  }
544
-
545
519
  console.log(`\n${folderErrorsLength}\n${intImagesErrorsLength}\n${fileTypeErrorsLength}\n${filenameErrorsLength}\n`);
546
520
  };
547
-
548
521
  exports.summaryLogs = summaryLogs;