|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
/** |
|
6
|
|
|
* @internal |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
use Illuminate\Support\Str; |
|
10
|
|
|
|
|
11
|
|
|
require_once __DIR__.'/../../../vendor/autoload.php'; |
|
12
|
|
|
|
|
13
|
|
|
$timeStart = microtime(true); |
|
14
|
|
|
|
|
15
|
|
|
$filesChanged = 0; |
|
16
|
|
|
|
|
17
|
|
|
$linesCounted = 0; |
|
18
|
|
|
|
|
19
|
|
|
$links = []; |
|
20
|
|
|
|
|
21
|
|
|
$warnings = []; |
|
22
|
|
|
|
|
23
|
|
|
// Buffer headings so we can check for style |
|
24
|
|
|
$headings = []; // [filename => [line => heading]] |
|
25
|
|
|
$checksHeadings = false; |
|
26
|
|
|
|
|
27
|
|
|
function find_markdown_files($dir): array |
|
28
|
|
|
{ |
|
29
|
|
|
$markdown_files = []; |
|
30
|
|
|
|
|
31
|
|
|
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); |
|
32
|
|
|
foreach ($iterator as $file) { |
|
33
|
|
|
// Skip _data directory |
|
34
|
|
|
if (str_contains($file->getPathname(), '_data')) { |
|
35
|
|
|
continue; |
|
36
|
|
|
} |
|
37
|
|
|
|
|
38
|
|
|
if ($file->isFile() && strtolower($file->getExtension()) == 'md') { |
|
39
|
|
|
$markdown_files[] = realpath($file->getPathname()); |
|
40
|
|
|
} |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
return $markdown_files; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
function handle_file(string $file): void |
|
47
|
|
|
{ |
|
48
|
|
|
echo 'Handling '.$file."\n"; |
|
49
|
|
|
|
|
50
|
|
|
normalize_lines($file); |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
function normalize_lines($filename): void |
|
54
|
|
|
{ |
|
55
|
|
|
$stream = file_get_contents($filename); |
|
56
|
|
|
|
|
57
|
|
|
$text = $stream; |
|
58
|
|
|
$text = str_replace("\r\n", "\n", $text); |
|
59
|
|
|
$text = str_replace("\t", ' ', $text); |
|
60
|
|
|
|
|
61
|
|
|
if (empty(trim($text))) { |
|
62
|
|
|
// Warn |
|
63
|
|
|
global $warnings; |
|
64
|
|
|
$warnings[] = "File $filename is empty"; |
|
65
|
|
|
|
|
66
|
|
|
return; |
|
67
|
|
|
} |
|
68
|
|
|
|
|
69
|
|
|
$lines = explode("\n", $text); |
|
70
|
|
|
$new_lines = []; |
|
71
|
|
|
|
|
72
|
|
|
$last_line = ''; |
|
73
|
|
|
$was_last_line_heading = false; |
|
74
|
|
|
$is_inside_fenced_code_block = false; |
|
75
|
|
|
$is_inside_fenced_fenced_code_block = false; |
|
76
|
|
|
$firstHeadingLevel = null; |
|
77
|
|
|
foreach ($lines as $index => $line) { |
|
78
|
|
|
global $linesCounted; |
|
79
|
|
|
$linesCounted++; |
|
80
|
|
|
|
|
81
|
|
|
/** Normalization */ |
|
82
|
|
|
|
|
83
|
|
|
// Remove multiple empty lines |
|
84
|
|
|
if (trim($line) == '' && trim($last_line) == '') { |
|
85
|
|
|
continue; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
// Make sure there is a space after headings |
|
89
|
|
|
if ($was_last_line_heading && trim($line) != '') { |
|
90
|
|
|
$new_lines[] = ''; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
// Make sure there are two empty lines before level 2 headings (but not if it's the first l2 heading) |
|
94
|
|
|
if ($is_inside_fenced_code_block !== true && str_starts_with($line, '## ') && $index > $firstHeadingLevel + 3) { |
|
95
|
|
|
$new_lines[] = ''; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
if ($firstHeadingLevel === null && str_starts_with($line, '# ')) { |
|
99
|
|
|
$firstHeadingLevel = $index; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
// Check if line is a heading |
|
103
|
|
|
if (str_starts_with($line, '##')) { |
|
104
|
|
|
$was_last_line_heading = true; |
|
105
|
|
|
global $headings; |
|
106
|
|
|
$headings[$filename][$index + 1] = $line; |
|
107
|
|
|
} else { |
|
108
|
|
|
$was_last_line_heading = false; |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
// Make sure there is a space before opening a fenced code block (search for ```language) |
|
112
|
|
|
if (str_starts_with($line, '```') && $line !== '```' && trim($last_line) != '') { |
|
113
|
|
|
if (! $is_inside_fenced_fenced_code_block) { |
|
114
|
|
|
$new_lines[] = ''; |
|
115
|
|
|
} |
|
116
|
|
|
} |
|
117
|
|
|
|
|
118
|
|
|
// Check if line is a fenced code block |
|
119
|
|
|
if (str_starts_with($line, '``')) { |
|
120
|
|
|
$is_inside_fenced_code_block = ! $is_inside_fenced_code_block; |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
// Check if line is an escaped fenced code block |
|
124
|
|
|
if (str_starts_with($line, '````')) { |
|
125
|
|
|
$is_inside_fenced_fenced_code_block = ! $is_inside_fenced_fenced_code_block; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
// Remove trailing spaces |
|
129
|
|
|
$line = rtrim($line); |
|
130
|
|
|
|
|
131
|
|
|
$new_lines[] = $line; |
|
132
|
|
|
$last_line = $line; |
|
133
|
|
|
|
|
134
|
|
|
/** Linting */ |
|
135
|
|
|
|
|
136
|
|
|
// if not inside fenced code block |
|
137
|
|
|
if (! $is_inside_fenced_code_block) { |
|
138
|
|
|
// Add any links to buffer, so we can check them later |
|
139
|
|
|
preg_match_all('/\[([^\[]+)]\((.*)\)/', $line, $matches); |
|
140
|
|
|
if (count($matches) > 0) { |
|
141
|
|
|
foreach ($matches[2] as $match) { |
|
142
|
|
|
// If link is for an anchor, prefix the filename |
|
143
|
|
|
if (str_starts_with($match, '#')) { |
|
144
|
|
|
$match = 'ANCHOR_'.basename($filename).$match; |
|
145
|
|
|
} |
|
146
|
|
|
|
|
147
|
|
|
global $links; |
|
148
|
|
|
$links[] = [ |
|
149
|
|
|
'filename' => $filename, |
|
150
|
|
|
'line' => $index + 1, |
|
151
|
|
|
'link' => $match, |
|
152
|
|
|
]; |
|
153
|
|
|
} |
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
// Check for un-backtick-ed inline code |
|
157
|
|
|
// If line contains $ |
|
158
|
|
|
if (str_contains($line, '$') && ! str_contains($line, '[Blade]:') && ! str_contains($line, '$ php')) { |
|
159
|
|
|
// Check character before the $ is not a backtick |
|
160
|
|
|
$pos = strpos($line, '$'); |
|
161
|
|
|
if ($pos > 0) { |
|
162
|
|
|
$charBefore = substr($line, $pos - 1, 1); |
|
163
|
|
|
if ($charBefore !== '`') { |
|
164
|
|
|
global $warnings; |
|
165
|
|
|
$warnings['Inline code'][] = sprintf('Unformatted inline code found in %s:%s', $filename, $index + 1); |
|
166
|
|
|
} |
|
167
|
|
|
} |
|
168
|
|
|
} |
|
169
|
|
|
// If line contains command |
|
170
|
|
|
if (str_contains($line, 'php hyde') && ! str_contains($line, '[Blade]:') && ! str_contains($line, '$ php')) { |
|
171
|
|
|
// Check character before the php hyde is not a backtick |
|
172
|
|
|
$pos = strpos($line, 'php hyde'); |
|
173
|
|
|
if ($pos > 0) { |
|
174
|
|
|
$charBefore = substr($line, $pos - 1, 1); |
|
175
|
|
|
if ($charBefore !== '`') { |
|
176
|
|
|
global $warnings; |
|
177
|
|
|
$warnings['Inline code'][] = sprintf('Unformatted inline command found in %s:%s', $filename, $index + 1); |
|
178
|
|
|
} |
|
179
|
|
|
} |
|
180
|
|
|
} |
|
181
|
|
|
// If word ends in .php |
|
182
|
|
|
if (str_contains($line, '.php') && ! str_contains($line, '[Blade]:') && ! str_contains($line, '$ php') && ! str_contains($line, 'http') && ! str_contains(strtolower($line), 'filepath')) { |
|
183
|
|
|
// Check character after the .php is not a backtick |
|
184
|
|
|
$pos = strpos($line, '.php'); |
|
185
|
|
|
if ($pos > 0) { |
|
186
|
|
|
$charAfter = substr($line, $pos + 4, 1); |
|
187
|
|
|
if ($charAfter !== '`') { |
|
188
|
|
|
global $warnings; |
|
189
|
|
|
$warnings['Inline code'][] = sprintf('Unformatted inline filename found in %s:%s', $filename, $index + 1); |
|
190
|
|
|
} |
|
191
|
|
|
} |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
// If word ends in .json |
|
195
|
|
|
if (str_contains($line, '.json') && ! str_contains($line, '[Blade]:') && ! str_contains($line, '$ json') && ! str_contains($line, 'http') && ! str_contains(strtolower($line), 'filepath')) { |
|
196
|
|
|
// Check character after the .json is not a backtick |
|
197
|
|
|
$pos = strpos($line, '.json'); |
|
198
|
|
|
if ($pos > 0) { |
|
199
|
|
|
$charAfter = substr($line, $pos + 5, 1); |
|
200
|
|
|
if ($charAfter !== '`') { |
|
201
|
|
|
global $warnings; |
|
202
|
|
|
$warnings['Inline code'][] = sprintf('Unformatted inline filename found in %s:%s', $filename, $index + 1); |
|
203
|
|
|
} |
|
204
|
|
|
} |
|
205
|
|
|
} |
|
206
|
|
|
// if word ends with () |
|
207
|
|
|
if (str_contains($line, '()') && ! str_contains($line, '[Blade]:')) { |
|
208
|
|
|
// Check character after the () is not a backtick |
|
209
|
|
|
$pos = strpos($line, '()'); |
|
210
|
|
|
if ($pos > 0) { |
|
211
|
|
|
$charAfter = substr($line, $pos + 2, 1); |
|
212
|
|
|
if ($charAfter !== '`') { |
|
213
|
|
|
global $warnings; |
|
214
|
|
|
$warnings['Inline code'][] = sprintf('Unformatted inline function found in %s:%s', $filename, $index + 1); |
|
215
|
|
|
} |
|
216
|
|
|
} |
|
217
|
|
|
} |
|
218
|
|
|
|
|
219
|
|
|
// Check for invalid command signatures |
|
220
|
|
|
if (str_contains($line, 'php hyde')) { |
|
221
|
|
|
// Extract signature from line |
|
222
|
|
|
$start = strpos($line, 'php hyde'); |
|
223
|
|
|
$substr = substr($line, $start); |
|
224
|
|
|
$explode = explode(' ', $substr, 3); |
|
225
|
|
|
$signature = $explode[0].' '.$explode[1].' '.$explode[2]; |
|
226
|
|
|
$end = strpos($signature, '`'); |
|
227
|
|
|
if ($end === false) { |
|
228
|
|
|
$end = strpos($signature, '<'); |
|
229
|
|
|
if ($end === false) { |
|
230
|
|
|
$end = strlen($signature); |
|
231
|
|
|
} |
|
232
|
|
|
} |
|
233
|
|
|
$signature = substr($signature, 0, $end); |
|
234
|
|
|
$signatures = getSignatures(); |
|
235
|
|
|
if (! in_array($signature, $signatures)) { |
|
236
|
|
|
global $warnings; |
|
237
|
|
|
$warnings['Invalid command signatures'][] = sprintf('Invalid command signature \'%s\' found in %s:%s', $signature, $filename, $index + 1); |
|
238
|
|
|
} |
|
239
|
|
|
} |
|
240
|
|
|
} |
|
241
|
|
|
|
|
242
|
|
|
// Check if line is too long |
|
243
|
|
|
if (strlen($line) > 120) { |
|
244
|
|
|
global $warnings; |
|
245
|
|
|
// $warnings[] = 'Line '.$linesCounted.' in file '.$filename.' is too long'; |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
// Warn if documentation contains legacy markers (experimental, beta, etc) |
|
249
|
|
|
$markers = ['experimental', 'beta', 'alpha', 'v0.']; |
|
250
|
|
|
foreach ($markers as $marker) { |
|
251
|
|
|
if (str_contains($line, $marker)) { |
|
252
|
|
|
global $warnings; |
|
253
|
|
|
$warnings['Legacy markers'][] = sprintf('Legacy marker found in %s:%s Found "%s"', $filename, $index + 1, $marker); |
|
254
|
|
|
} |
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
|
|
// Warn when legacy terms are used (for example slug instead of identifier/route key) |
|
258
|
|
|
$legacyTerms = [ |
|
259
|
|
|
'slug' => '"identifier" or "route key"', |
|
260
|
|
|
'slugs' => '"identifiers" or "route keys"', |
|
261
|
|
|
]; |
|
262
|
|
|
|
|
263
|
|
|
foreach ($legacyTerms as $legacyTerm => $newTerm) { |
|
264
|
|
|
if (str_contains(strtolower($line), $legacyTerm)) { |
|
265
|
|
|
global $warnings; |
|
266
|
|
|
$warnings['Legacy terms'][] = sprintf('Legacy term found in %s:%s Found "%s", should be %s', $filename, $index + 1, $legacyTerm, $newTerm); |
|
267
|
|
|
} |
|
268
|
|
|
} |
|
269
|
|
|
} |
|
270
|
|
|
|
|
271
|
|
|
$new_content = implode("\n", $new_lines); |
|
272
|
|
|
$new_content = trim($new_content)."\n"; |
|
273
|
|
|
file_put_contents($filename, $new_content); |
|
274
|
|
|
|
|
275
|
|
|
if ($new_content !== $stream) { |
|
276
|
|
|
global $filesChanged; |
|
277
|
|
|
$filesChanged++; |
|
278
|
|
|
} |
|
279
|
|
|
} |
|
280
|
|
|
|
|
281
|
|
|
$dir = __DIR__.'/../../../docs'; |
|
282
|
|
|
$markdownFiles = find_markdown_files($dir); |
|
283
|
|
|
|
|
284
|
|
|
foreach ($markdownFiles as $file) { |
|
285
|
|
|
handle_file($file); |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
// Just to make PhpStorm happy |
|
289
|
|
|
$links[] = [ |
|
290
|
|
|
'filename' => '', |
|
291
|
|
|
'line' => 1, |
|
292
|
|
|
'link' => '', |
|
293
|
|
|
]; |
|
294
|
|
|
|
|
295
|
|
|
if (count($links) > 0) { |
|
296
|
|
|
$uniqueLinks = []; |
|
297
|
|
|
|
|
298
|
|
|
foreach ($links as $data) { |
|
299
|
|
|
$link = $data['link']; |
|
300
|
|
|
$filename = $data['filename']; |
|
301
|
|
|
$line = $data['line']; |
|
302
|
|
|
|
|
303
|
|
|
if (str_starts_with($link, 'http')) { |
|
304
|
|
|
// Check for outdated links |
|
305
|
|
|
// laravel.com/docs/9.x |
|
306
|
|
|
if (str_contains($link, 'laravel.com/docs/9.x')) { |
|
307
|
|
|
$warnings['Outdated links'][] = "Outdated documentation link to $link found in $filename:$line"; |
|
308
|
|
|
} |
|
309
|
|
|
continue; |
|
310
|
|
|
} |
|
311
|
|
|
|
|
312
|
|
|
if (str_starts_with($link, '#')) { |
|
313
|
|
|
continue; |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
// Remove hash for anchors |
|
317
|
|
|
$link = explode('#', $link)[0]; |
|
318
|
|
|
// Remove anything before spaces (image alt text) |
|
319
|
|
|
$link = explode(' ', $link)[0]; |
|
320
|
|
|
// Trim any non-alphanumeric characters from the end of the link |
|
321
|
|
|
$link = rtrim($link, '.,;:!?)'); |
|
322
|
|
|
|
|
323
|
|
|
if (! str_starts_with($link, 'ANCHOR_')) { |
|
324
|
|
|
// Add to new unique array |
|
325
|
|
|
$uniqueLinks[$link] = "$filename:$line"; |
|
326
|
|
|
} |
|
327
|
|
|
} |
|
328
|
|
|
|
|
329
|
|
|
$base = __DIR__.'/../../../docs'; |
|
330
|
|
|
// find all directories in the docs folder |
|
331
|
|
|
$directories = array_filter(glob($base.'/*'), 'is_dir'); |
|
332
|
|
|
|
|
333
|
|
|
foreach ($uniqueLinks as $link => $location) { |
|
334
|
|
|
// Check uses pretty urls |
|
335
|
|
|
if (str_ends_with($link, '.html')) { |
|
336
|
|
|
$warnings['Bad links'][] = "Link to $link in $location should not use .html extension"; |
|
337
|
|
|
continue; |
|
338
|
|
|
} |
|
339
|
|
|
|
|
340
|
|
|
// Check does not end with .md |
|
341
|
|
|
if (str_ends_with($link, '.md')) { |
|
342
|
|
|
$warnings['Bad links'][] = "Link to $link in $location must not use .md extension"; |
|
343
|
|
|
continue; |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
// Check if file exists |
|
347
|
|
|
if (! file_exists($base.'/'.$link)) { |
|
348
|
|
|
$hasMatch = false; |
|
349
|
|
|
foreach ($directories as $directory) { |
|
350
|
|
|
if (file_exists($directory.'/'.$link.'.md')) { |
|
351
|
|
|
$hasMatch = true; |
|
352
|
|
|
break; |
|
353
|
|
|
} |
|
354
|
|
|
} |
|
355
|
|
|
|
|
356
|
|
|
if (! $hasMatch) { |
|
357
|
|
|
// Check that link is not for search (dynamic page) |
|
358
|
|
|
if (! str_contains($link, 'search')) { |
|
359
|
|
|
$warnings['Broken links'][] = "Broken link to $link found in $location"; |
|
360
|
|
|
} |
|
361
|
|
|
} |
|
362
|
|
|
} |
|
363
|
|
|
} |
|
364
|
|
|
} |
|
365
|
|
|
|
|
366
|
|
|
function getSignatures(): array |
|
367
|
|
|
{ |
|
368
|
|
|
static $signatures = null; |
|
369
|
|
|
|
|
370
|
|
|
if ($signatures === null) { |
|
371
|
|
|
$cache = __DIR__.'/../cache/hyde-signatures.php'; |
|
372
|
|
|
if (file_exists($cache)) { |
|
373
|
|
|
$signatures = include $cache; |
|
374
|
|
|
} else { |
|
375
|
|
|
$signatures = [ |
|
376
|
|
|
// Adds any hidden commands we know exist |
|
377
|
|
|
'php hyde list', |
|
378
|
|
|
'php hyde change:sourceDirectory', |
|
379
|
|
|
]; |
|
380
|
|
|
$commandRaw = shell_exec('cd ../../../ && php hyde list --raw'); |
|
381
|
|
|
foreach (explode("\n", $commandRaw) as $command) { |
|
382
|
|
|
$command = Str::before($command, ' '); |
|
383
|
|
|
$signatures[] = trim('php hyde '.$command); |
|
384
|
|
|
} |
|
385
|
|
|
file_put_contents($cache, '<?php return '.var_export($signatures, true).';'); |
|
386
|
|
|
} |
|
387
|
|
|
} |
|
388
|
|
|
|
|
389
|
|
|
return $signatures; |
|
390
|
|
|
} |
|
391
|
|
|
|
|
392
|
|
|
// Just to make PhpStorm happy |
|
393
|
|
|
$headings['foo.md'][1] = '## Bar'; |
|
394
|
|
|
|
|
395
|
|
|
if ($checksHeadings && count($headings)) { |
|
396
|
|
|
foreach ($headings as $filename => $fileHeadings) { |
|
397
|
|
|
$headingLevels = []; |
|
398
|
|
|
foreach ($fileHeadings as $heading) { |
|
399
|
|
|
$headingLevel = substr_count($heading, '#'); |
|
400
|
|
|
$headingLevels[] = $headingLevel; |
|
401
|
|
|
|
|
402
|
|
|
// Check for style: 1-2 headings should be title case, 3+ should be sentence case |
|
403
|
|
|
$headingText = trim(str_replace('#', '', $heading)); |
|
404
|
|
|
$titleCase = Hyde\make_title($headingText); |
|
405
|
|
|
$alwaysUppercase = ['PHP', 'HTML', 'CLI']; |
|
406
|
|
|
$alwaysLowercase = ['to']; |
|
407
|
|
|
$titleCase = str_ireplace($alwaysUppercase, $alwaysUppercase, $titleCase); |
|
408
|
|
|
$titleCase = str_ireplace($alwaysLowercase, $alwaysLowercase, $titleCase); |
|
409
|
|
|
|
|
410
|
|
|
$isTitleCase = $headingText === $titleCase; |
|
411
|
|
|
$sentenceCase = Str::ucfirst($headingText); |
|
412
|
|
|
$isSentenceCase = $headingText === $sentenceCase; |
|
413
|
|
|
$something = false; |
|
414
|
|
|
if ($headingLevel < 3) { |
|
415
|
|
|
if (! $isTitleCase) { |
|
416
|
|
|
$warnings['Headings'][] = "Heading '$headingText' should be title case in $filename (expected '$titleCase')"; |
|
417
|
|
|
} |
|
418
|
|
|
} else { |
|
419
|
|
|
if (! $isSentenceCase) { |
|
420
|
|
|
$warnings['Headings'][] = "Heading '$headingText' should be sentence case in $filename (expected '$sentenceCase')"; |
|
421
|
|
|
} |
|
422
|
|
|
} |
|
423
|
|
|
} |
|
424
|
|
|
} |
|
425
|
|
|
} |
|
426
|
|
|
|
|
427
|
|
|
if (count($warnings) > 0) { |
|
428
|
|
|
echo "\n\033[31mWarnings:\033[0m \033[33m".count($warnings, COUNT_RECURSIVE) - count($warnings)." found \033[0m \n"; |
|
429
|
|
|
foreach ($warnings as $type => $messages) { |
|
430
|
|
|
echo "\n\033[33m$type:\033[0m \n"; |
|
431
|
|
|
foreach ($messages as $message) { |
|
432
|
|
|
echo " - $message\n"; |
|
433
|
|
|
} |
|
434
|
|
|
} |
|
435
|
|
|
} |
|
436
|
|
|
|
|
437
|
|
|
$time = round((microtime(true) - $timeStart) * 1000, 2); |
|
438
|
|
|
$linesTransformed = number_format($linesCounted); |
|
439
|
|
|
$fileCount = count($markdownFiles); |
|
440
|
|
|
|
|
441
|
|
|
echo "\n\n\033[32mAll done!\033[0m Formatted, normalized, and validated $linesTransformed lines of Markdown in $fileCount files in {$time}ms\n"; |
|
442
|
|
|
|
|
443
|
|
|
if ($filesChanged > 0) { |
|
444
|
|
|
echo "\n\033[32m$filesChanged files were changed.\033[0m "; |
|
445
|
|
|
} else { |
|
446
|
|
|
echo "\n\033[32mNo files were changed.\033[0m "; |
|
447
|
|
|
} |
|
448
|
|
|
$warningCount = count($warnings, COUNT_RECURSIVE) - count($warnings); |
|
449
|
|
|
if ($warningCount > 0) { |
|
450
|
|
|
echo sprintf("\033[33m%s %s found.\033[0m", $warningCount, $warningCount === 1 ? 'warning' : 'warnings'); |
|
451
|
|
|
if (file_exists(__DIR__.'/../cache/last-run-warnings-count.txt')) { |
|
452
|
|
|
$lastRunWarningsCount = (int) file_get_contents(__DIR__.'/../cache/last-run-warnings-count.txt'); |
|
453
|
|
|
if ($warningCount < $lastRunWarningsCount) { |
|
454
|
|
|
echo sprintf(' Good job! You fixed %d %s!', $lastRunWarningsCount - $warningCount, $lastRunWarningsCount - $warningCount === 1 ? 'warning' : 'warnings'); |
|
455
|
|
|
} elseif ($warningCount > $lastRunWarningsCount) { |
|
456
|
|
|
echo sprintf(' Uh oh! You introduced %d new %s!', $warningCount - $lastRunWarningsCount, $warningCount - $lastRunWarningsCount === 1 ? 'warning' : 'warnings'); |
|
457
|
|
|
} |
|
458
|
|
|
} |
|
459
|
|
|
} |
|
460
|
|
|
file_put_contents(__DIR__.'/../cache/last-run-warnings-count.txt', $warningCount); |
|
461
|
|
|
echo "\n"; |
|
462
|
|
|
|
|
463
|
|
|
// If --git flag is passed, make a git commit |
|
464
|
|
|
if (isset($argv[1]) && $argv[1] === '--git') { |
|
465
|
|
|
if ($filesChanged > 0) { |
|
466
|
|
|
echo "\n\033[33mCommitting changes to git...\033[0m\n"; |
|
467
|
|
|
passthru('git commit -am "Format Markdown"'); |
|
468
|
|
|
} else { |
|
469
|
|
|
echo "\n\033[33mNo changes to commit\033[0m\n"; |
|
470
|
|
|
} |
|
471
|
|
|
} |
|
472
|
|
|
|