Skip to content

Instantly share code, notes, and snippets.

@andreich1980
Last active November 28, 2020 13:44
Show Gist options
  • Save andreich1980/a58deabb237e13c162b581530d262b93 to your computer and use it in GitHub Desktop.
Save andreich1980/a58deabb237e13c162b581530d262b93 to your computer and use it in GitHub Desktop.
Script that helps to detect broken links in md files (specifically - laravel/docs)
<?php
/**
* Parses *.md files in the current directory for broken links.
* - [Link](#broken-anchor) without <a name="broken-anchor"></a> within the same file
* - [Link](another-file#broken-anchor) without <a name="broken-anchor"></a> in the another-file.md
*/
$ok = $fail = 0;
foreach (glob('*.md') as $file) {
if ($brokenLinks = findBrokenLinks($file)) {
printError($file, $brokenLinks);
$fail++;
} else {
printOk($file, $brokenLinks);
$ok++;
}
}
print PHP_EOL . "OK: {$ok}. FAIL: {$fail}.";
function findBrokenLinks($file)
{
$contents = file_get_contents($file);
// Find all the links
preg_match_all('/\[[^]]+\]\(([-a-z0-9#]+)\)/', $contents, $links);
// Exclude external links
$links = array_filter($links[1], function ($link) {
return 'http' !== substr($link, 0, 4) && 'ftp' !== substr($link, 0, 3);
});
// Filter broken links
return array_filter($links, function ($link) use ($contents) {
if ('#' !== substr($link, 0, 1)) {
[$file, $link] = parseFileData($link);
// if the link was [Link](another-file) without an achor then just check file existance
if (is_null($link)) {
return !file_exists($file);
}
$contents = file_get_contents($file);
} else {
$link = substr($link, 1);
}
return false === strpos($contents, "<a name=\"{$link}\"></a>");
});
}
function parseFileData($link)
{
$linkData = explode('#', $link);
$link = $linkData[1] ?? null;
$file = "{$linkData[0]}.md";
return [
file_exists($file) ? file_get_contents($file) : null,
$linkData[1] ?? null
];
}
function printOk($file, $links)
{
printInfo($file, $links, "OK", "\033[32m");
}
function printError($file, $links)
{
printInfo($file, $links, "FAIL", "\033[31m");
}
function printInfo($file, $links, $caption = "INFO", $color = "\033[0m")
{
$default = "\033[0m";
print "[{$color}{$caption}{$default}] {$file}" . PHP_EOL;
foreach ($links as $link) {
print " - {$link}" . PHP_EOL;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment